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:
- App router example GitHub - hyundotio/nextjs-ts-cesium-example: A TypeScript Next.js project (App router) with Cesium that actually builds and runs on Vercel
- Page router example GitHub - hyundotio/next-ts-pagerouter-cesium-example: A TypeScript Next.js project (Page router) with Cesium that actually builds and runs on Vercel
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 pluginpatterns
entry. I thought Nextjs’ swcminifier was trying to process already minified/processed Cesium files in thepublic
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 aReact.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"
NOTimport {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!