Modular Structure in CesiumJS Offers Better Dependency Management
With the release of CesiumJS 1.100 on December 1, it’s possible to download either the entire CesiumJS release or just a subset of the Cesium library through smaller packages. This change gives applications that use only a subset of Cesium’s capabilities access to smaller, more specific packages.
CesiumJS is an extensive library with a lot of functionality to meet a broad range of use cases. While some users may use the whole stack by embedding the CesiumViewer
in their application and using all the features that the Timeline
and Animation
widgets bring, others may only want a lean interface through the CesiumWidget
, and still others may only want to use the geospatial math library in Core
.
Given the diversity of our user community and the domains CesiumJS is used for, the benefits of a modularized structure of packages are apparent: users can choose to depend on only what they want to use in their application. The benefits go beyond producing a leaner bundle; this change eliminates the need to install all of the direct dependencies that are synced with the existing cesium
npm package. It also reduces the surface area of the API that the user is supposed to learn, and provides flexibility in selecting when and how users update their dependencies.
To start, these smaller packages take the form of “engine” and “widgets.” We plan on maintaining our regular monthly release schedule for CesiumJS. For example, when CesiumJS 1.100 was made available December 1, engine 1.0 and widgets 1.0 were also released.
Engine package
The engine package is the core runtime components of CesiumJS, including everything except the Widgets folder found in the combined CesiumJS release. The one exception here is that CesiumWidget has been moved from the widgets
to engine
. This provides a lean and minimal way of adding CesiumJS to the browser.
So, if you’re only using the engine package, you can get started with the following snippet:
import { CesiumWidget } from “@cesium/engine”;
import “@cesium/engine/Source/Widget/CesiumWidget.css”;
const widget = new CesiumWidget(“cesium-container”);
Widgets package
The widgets package contains all the different UI widgets that are part of the combined CesiumJS package. These include the Viewer
, Timeline
, Animation
, etc., along with the different mixins. To get started with the widgets package, you can use the following snippet:
import { Viewer } from “@cesium/widgets”;
import “@cesium/widgets/Source/widgets.css”;
const viewer = new Viewer(“cesium-container”);
Since widgets
depends on engine
, the engine package will automatically be installed when you install widgets
.
Implementation details
We use npm workspaces to impose a monorepo structure. These packages can be found in the root level packages
directory and will be published under the @cesium
scope, i.e., @cesium/engine
and @cesium/widgets
.
As compared to the combined CesiumJS package, which includes pre-bundled artifacts such as Cesium.js
, index.js
and index.cjs
, these newer packages will be shipped in a lean configuration, as ES modules with TypeScript definitions, as is the standard for modern packages. This will allow users to employ the bundling tools of their choice for their applications and take advantage of features like tree-shaking, or dead code elimination.
Also, as per npm best practice, these packages will follow semantic versioning, which lets users clearly understand the scope of changes between versions and prevent cases where allowing npm to automatically update versions would result in broken builds.
In terms of what these changes look like in the repository or the combined release, all source files from the root level Source
folder have been moved into the respective package folder. For example, Scene.js
has moved from Source/Scene/Scene.js
to packages/engine/Source/Scene/Scene.js
. And Viewer.js
has moved from Source/Widgets/Viewer/Viewer.js
to packages/widgets/Source/Viewer/Viewer.js
. Any direct dependencies included in the source code have been moved to the ThirdParty
folder within each package’s Source
folder.
When working within the repository, each package also comes with its own simple scripts:
build
- Creates the package’s entry module index.js
, bundles the Specs
build-ts
- Generates the TypeScript definitions file
test
- Runs tests
coverage
- Generates coverage report
To minimize impact on applications that depend on the combined CesiumJS release structure, static assets found in Assets
, ThirdParty
, and Widgets
are still copied to the root level Source
folder at the time of publishing.
Next steps
These changes are another important step of our plan to continue modernizing the CesiumJS library and they build on the previous improvements to our source code, tooling, and build processes. In the future, we hope to be able to break the packages down along even finer lines, such as publishing a core
package that contains all the geospatial math classes like Cartesian3
, etc.
Please share your feedback on GitHub or the community forum.