Success! Next.js 14, TypeScript + Cesium on Vercel

Hey all, I’ve been a user of CesiumJS for awhile and I thought I’d give back to project.

I had trouble finding a turn key solution on getting Cesium working well with NextJS. I saw some tutorials that worked with older versions of NextJS but it didn’t have an example on how to properly get it working with TypeScript nor did it work on Vercel.

For people who don’t wanna read more… here’s the GitHub repo that I made that works in both dev, build, as well as in deployed (Vercel) environments:

My journey

Next.js Build issues
Copy Webpack Plugin to copy required files from node_modules to a publicly accessible folder, i.e., /public in Next.js… This was a good starting point as I couldn’t get Cesium to load any other way. However, only npm run dev worked but not npm run build. It complained about 'import and 'export' cannot be used outside of module during the build process.

  • The crummy fix: was to flag Nextjs swcminify: false, but that has a pretty large implication on the enitre project.
  • The good fix: was to add a info: { minimized: true } in the Copy WebPack plugin patterns entry. I thought Nextjs’ swcminifier was trying to process already minified/processed Cesium files in the public folder but it was actually the Copy WebPack plugin (Terser).

Vercel 500 status issues
Once I found a solution that led to a successful build and deployed it to Vercel, I’ve experienced 500 status errors when I visited SOME but not all pages with Cesium mounted. The error was something of: EMFILE: too many open files error. I’m not 100% sure why this problem was caused but it seemed to happen in pages with getServerSideProps (even though it was passing just a dummy string) whether that was a coincidence or not, I don’t know.

  • The fix: Importing Cesium via a Promise in a React.useEffect solved this problem.

TypeScript
The other was getting all proper typings working with #2 solution.

  • The fix: This was solved by creating a “wrapped” type of sorts and only using typings straight from import type from {x} "cesium" NOT import {x} from "cesium" to make sure Cesium wasn’t imported again.

Note: I have Cesium viewer tied to a ref because it would mount it twice otherwise during development mode with the latest version of React.


React
Another thing I missed was a dev environment double-render example. With NextJs 13.4+, React strcit mode is enabled by default on the dev environment. So if you have an initializing function that adds things like Primitives for example, you need to have a cleanup function so the same things don’t get added twice. I added an example in the repo on May 19 2024 tackling this. Or you can turn off React Strict mode… but I do not suggest you doing that!


Anyways, I hope this is helpful and saves people time trying to get Cesium working with Nextjs 14 and TypeScript!

1 Like

i encountered thesame problem and this was very helpfull

1 Like

Hi thank you for your work. It has helped me a lot.

I was wondering if importing Cesium inside the useEffect instead of importing and using it like below is only for the problem when putting it on Vercel?

import * as Cesium from ‘cesium’;

I’m worried because I need to use a library that uses Cesium that we already made.

Thanks.