CesiumJS Build Tooling Revamp

Hi all,

We’re considering a new approach for building cesiumjs and we’re looking for your insight and input.

Cesium is a big library made up of hundreds of individual modules. You can load each of these modules individually in the browser, or run a build process to package all those modules together into one file, or bundle, which can then be loaded in the browser. Our bundling is currently being done using rollup.

We’re looking at moving to a new build tool. With this, we could include third-party modules directly, rather than manually copying, and preprocess to perform any necessary code transformation before bundling all the modules for the web.

One appeal of preprocessing would be the ability for us to transpile ES6+ code to something compatible with all supported browsers. Up until now, we’ve been limited to using JavaScript features supported by whatever browser has the lowest level of support. For instance, we cannot use import statements in our web worker code since it’s not yet supported in Firefox. Transpiling would let us make some much needed short-term improvements, and make other changes in the future like migrate to TypeScript if/when we chose to commit to it.

However, this means that during development we’ll need to rebuild at least a portion of the code whenever the source code changes. The goal is to make sure this extra step is fast enough that the developer does not need to wait to see the results.

We’re looking mainly at these two tools:

  • esbuild is what we’ve been eyeing as we’ve gotten the chance to use it in some of our own internal projects. The appeal is its speed, being significantly fast than rollup or webpack and having a more minimal configuration.
  • webpack is a popular tool which is used by many cesium app developers (and we’ve written a tutorial on how to build Cesium app with it). While its popularity and pervasiveness are pluses, it tends to be slower and require a lot of configuration.

TLDR; We’re revamping our build process and are considering esbuild or maybe webpack to do so. We’re looking for any thoughts you may have on these or other tools, or any general tips.

Thanks!

4 Likes

Now there are a lot of bundlers and workflow tools to choose from.

Like vite, it uses esbuild to prebuild dependencies, and for production stability, rollup is used.

But considering CesiumJS has static assets, /Assets, /Workers, /ThirdParty, /Widgets(styles) …, keep using gulp will be better.

I don’t have any suggestions, but I think migrating to Typescript in time can reduce a lot of type-checking code.

But thinking CesiumJS in most time is a JavaScript lib, not a WebApp that may includes UI framework and other tons of tools to build SPA or SSR apps, use rollup + gulp to build production output maybe better than webpack?

I do like esbuild (I use it with Vite), the problem comes when HMR doesn’t know what to do with resources that touch the graphics pipeline.

Thanks for the feedback all! I wrote up an issue summarizing the next steps: Revisit CesiumJS build tooling · Issue #10373 · CesiumGS/cesium · GitHub

There’s now an initial implementation of this in Streamline build processes with esbuild by ggetz · Pull Request #10399 · CesiumGS/cesium · GitHub.

We would love to get any feedback, especially in regards to the packaged build output. As of this PR, the most notable change is there are no more AMD/UMD style modules; Instead we output bundled IIFE for the browser, generic ESM modules, or CJS for node.

It’s still possible to use individual modules in the Source directory as before, though the Workers are packaged a bit differently now so we can get finally get rid of RequireJS.

Still looking for any feedback on this PR. :smiley:

1 Like

I have a question about this new build tooling setup. In our application we have been “namespacing” our Cesium so it doesn’t reside directly on the window, but on another object. I’ve been pulling this off by modifying the Cesium.js file so that it uses our namespace object instead of globalThis.

Like this:

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (global = typeof namespaceObject !== 'undefined' ? namespaceObject : namespaceObject || namespaceObject, factory(namespaceObject .Cesium = {}));
})(this, (function (exports) { 'use strict';
...

But in the new Cesium.js, I can’t find any sort of place where I can do this. The only thing I see in there that uses globalThis is in the DOMPurify section. I’m not even really sure how it’s assigning the Cesium object to the window at all. Is it relying on DOMPurify’s getGlobal method?

Is there anything in the tooling that can reassign the object that receives Cesium?

Just to confirm, you’re looking to set myGlobalObject.Cesium, such that you can use the library like this:

const viewer = myGlobalObject.Cesium.Viewer(...);

Correct?

As of 1.97, Cesium is no longer AMD. It has been split into two distributables: Cesium.js which is IIFE and adds Cesium to the global namespace when loaded; and index.js which is ESM and exports individual modules.

Assuming you’re looking to do this in the browser, you could add a new cesium loader file, something like load-cesium-esm.js which loads all of the modules from index.js and assigns it to the global object.

import * as Cesium from "Build/Cesium/index.js";

myGlobalObject.Cesium = Cesium;

Then, that file will need to load with a scrip tag where type="module".

<script type="module" src="load-cesium-esm.js"></script>

Or, if your application files are already loaded with type="module", you don’t need that additional file at all, and can add that import statement to the top of your existing file.

Thanks! I just had to set the CESIUM_BASE_URL value and it seems to be working.

1 Like