Webpack is a popular and powerful tool for bundling JavaScript modules. It allows developers to structure their code and assets in an intuitive way and to load different kinds of files as needed with simple require statements. When building, it will trace code dependencies and pack these modules into one or more bundles that are loaded by the web browser. This tutorial is a good place to start if you’d like to use CesiumJS to develop a more advanced web application. If you’re new to Cesium and are looking to learn to build your first sample app, take a look at our Getting Started Tutorial.
You'll learn how to:
- Build a simple web app from the ground up using webpack
- Integrate the Cesium npm package into your web app
- A basic understanding of the command line, JavaScript, and web development.
- Node.js installed. We recommend using the latest LTS version.
- Create a new directory for your app.
- Open a console window and navigate to the directory.
- Run
npm init
and enter in the requested details about your application. If you are unsure about any prompts, pressEnter
to use the default value. You can modify these details at any point in thepackage.json
file thatnpm init
creates.
- Create a
src
directory for your app code. When you build the app, webpack will automatically produce distribution files in a directory nameddist
. - Create the files
index.html
andindex.js
in thesrc
directory added in step 1. - Add the following code to
src/index.html
. This will serve as a boilerplate HTML page to get us started.<!doctype html> <html> <head> <meta charset="utf-8" /> </head> <body> <p>Hello World!</p> </body> </html>
- Add the following code to
src/index.js
. This will serve as our boilerplate JavaScript code.console.log("Hello World!");
- Create the file
src/css/main.css
and add the following css codehtml, body, #cesiumContainer { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; }
-
Install webpack by running
npm install --save-dev webpack
. The filespackage-lock.json
andpackage.json
should appear in your main directory. You should also see a new folder in your main directory namednode_modules
. -
Create the file
webpack.config.js
in your main directory. -
Define our webpack configuration object by adding the following code to
webpack.config.js
const path = require("path"); const webpack = require("webpack"); module.exports = { context: __dirname, entry: { app: "./src/index.js", }, output: { filename: "app.js", path: path.resolve(__dirname, "dist"), }, };
In this code,
context
specifies the base path for your files.entry
is used to specify bundles andsrc/index.js
is our entry point. Webpack will output the bundelapp.js
to the folderdist
, that webpack will create at runtime. -
Webpack loads everything like a module. loaders are used to load CSS and other asset files. Install the style-loader, css-loader, and url-loader using
npm install --save-dev style-loader css-loader url-loader
. Feel free to install any other loaders you may need in the future. Loaders can be installed at any point during this process. -
Update
webpack.config.js
by adding twomodule.rules
. The first rule should support CSS files and the second rule should support other static files. For each rule, definetest
for the types of files to load anduse
to specify the list of loaders.webpack.config.js
should look something like this.const path = require("path"); const webpack = require("webpack"); module.exports = { context: __dirname, entry: { app: "./src/index.js", }, output: { filename: "app.js", path: path.resolve(__dirname, "dist"), }, module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader"], }, { test: /\.(png|gif|jpg|jpeg|svg|xml|json)$/, use: ["url-loader"], }, ], }, };
-
To define
index.html
and inject our bundle into that page you will be using a webpack plugin called html-webpack-plugin. Use the commandnpm install --save-dev html-webpack-plugin
to install the necessary plugin. -
Require html-webpack-plugin in
webpack.config.js
by adding it to theplugins
section. Next, passsrc/index.html
as ourtemplate
. Finally, specify the mode option for webpack by addingmode: 'development'
towebpack.config.js
.webpack.config.js
should now look something likeconst path = require("path"); const webpack = require("webpack"); const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { context: __dirname, entry: { app: "./src/index.js", }, output: { filename: "app.js", path: path.resolve(__dirname, "dist"), }, module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader"], }, { test: /\.(png|gif|jpg|jpeg|svg|xml|json)$/, use: ["url-loader"], }, ], }, plugins: [ new HtmlWebpackPlugin({ template: "src/index.html", }), ], mode: "development", };
- In
package.json
, define the scripts that we can call withnpm
. Add thebuild
command.If done correctly,"scripts": { "build": "node_modules/.bin/webpack --config webpack.config.js" }
package.json
should look something like this.{ "name": "cesiumjs-webpack-tutorial", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "node_modules/.bin/webpack --config webpack.config.js" }, "author": "", "license": "ISC", "devDependencies": { "css-loader": "^6.2.0", "html-webpack-plugin": "^5.3.2", "style-loader": "^3.2.1", "url-loader": "^4.1.1", "webpack": "^5.50.0" } }
Please note that details of this json file will vary based on your selections in step 3 of Initialize an App with npm.
-
Run the command
npm run build
. Install CLI for webpack if necessary. Webpack CLI can be installed using the commandnpm install --save-dev webpack-cli
. -
Ensure that there are no errors and your output looks similar to
$ npm run build > [email protected] build > node_modules/.bin/webpack --config webpack.config.js asset app.js 1.22 KiB [emitted] (name: app) asset index.html 376 bytes [emitted] ./src/index.js 28 bytes [built] [code generated] webpack 5.50.0 compiled successfully in 86 ms
Please verify that the app.js
bundle and index.html
file are added to the dist
folder.
-
You will be using a webpack-dev-server to serve a development build and see our application in action. Run
npm install --save-dev webpack-dev-server
. -
Add a
start
script topackage.json
. This script should run the development server. Be sure to set the config file via the--config
flag and use the--open
flag to open the application in a a browser upon execution of the command.package.json
should look something like{ "name": "cesiumjs-webpack-tutorial", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "node_modules/.bin/webpack --config webpack.config.js", "start": "node_modules/.bin/webpack serve --config webpack.config.js --open" }, "author": "", "license": "ISC", "devDependencies": { "css-loader": "^6.2.0", "html-webpack-plugin": "^5.3.2", "style-loader": "^3.2.1", "url-loader": "^4.1.1", "webpack": "^5.50.0", "webpack-cli": "^4.7.2", "webpack-dev-server": "^3.11.2" } }
-
Run
npm start
and open http://localhost:8080/ in a web browser. -
Verify that you see Hello World!
CesiumJS is an open source JavaScript library for creating world-class 3D globes and maps. Thus, it is a rather large and complex library. In additional to JavaScript modules, it also includes static assets such as CSS, image, and json files. It includes web worker files to perform intensive calculations in separate threads. Unlike traditional npm modules, CesiumJS does not define an entry point because of the diverse ways in which the library is used. You will need to configure some additional options to use it with webpack.
First, define where CesiumJS is. This tutorial uses the source code, so webpack can include individual models and trace the dependencies. Alternatively, you can use the built (minified or unminified) version of CesiumJS. However, the modules are already combined and optimized, which gives us less flexibility.
-
Install the Cesium module from npm using the command
npm install --save-dev cesium
. -
Update
sourcePrefix
to tell CesiumJS that the version of AMD webpack uses to evaluaterequire
statements is not compliant with the standardtoUrl
function. In addition, add acesium
alias so we can reference it in our app code. After adding these changes,webpack.config.js
should look like// The path to the CesiumJS source code const cesiumSource = "node_modules/cesium/Source"; const cesiumWorkers = "../Build/Cesium/Workers"; const path = require("path"); const webpack = require("webpack"); const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { context: __dirname, entry: { app: "./src/index.js", }, output: { filename: "app.js", path: path.resolve(__dirname, "dist"), // Needed to compile multiline strings in Cesium sourcePrefix: "", }, amd: { // Enable webpack-friendly use of require in Cesium toUrlUndefined: true, }, resolve: { alias: { cesium: path.resolve(__dirname, cesiumSource), }, mainFiles: ["module", "main", "Cesium"], }, module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader"], }, { test: /\.(png|gif|jpg|jpeg|svg|xml|json)$/, use: ["url-loader"], }, ], }, plugins: [ new HtmlWebpackPlugin({ template: "src/index.html", }), ], mode: "development", };
-
Now, you must make sure the static CesiumJS asset, widget, and web worker files are served and loaded correctly. Use
copy-webpack-plugin
to copy static files to thedist
directory as part of the build process. To do this run the commandnpm install --save-dev copy-webpack-plugin
and updated the plugins array inwebpack.config.js
.webpack.config.js
should now look like// The path to the CesiumJS source code const cesiumSource = "node_modules/cesium/Source"; const cesiumWorkers = "../Build/Cesium/Workers"; const CopyWebpackPlugin = require("copy-webpack-plugin"); const path = require("path"); const webpack = require("webpack"); const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { context: __dirname, entry: { app: "./src/index.js", }, output: { filename: "app.js", path: path.resolve(__dirname, "dist"), sourcePrefix: "", }, amd: { // Enable webpack-friendly use of require in Cesium toUrlUndefined: true, }, resolve: { alias: { cesium: path.resolve(__dirname, cesiumSource), }, mainFiles: ["module", "main", "Cesium"], }, module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader"], }, { test: /\.(png|gif|jpg|jpeg|svg|xml|json)$/, use: ["url-loader"], }, ], }, plugins: [ new HtmlWebpackPlugin({ template: "src/index.html", }), // Copy Cesium Assets, Widgets, and Workers to a static directory new CopyWebpackPlugin({ patterns: [ { from: path.join(cesiumSource, cesiumWorkers), to: "Workers" }, { from: path.join(cesiumSource, "Assets"), to: "Assets" }, { from: path.join(cesiumSource, "Widgets"), to: "Widgets" }, ], }), new webpack.DefinePlugin({ // Define relative base path in cesium for loading assets CESIUM_BASE_URL: JSON.stringify(""), }), ], mode: "development", };
-
Updated
index.js
with CesiumJS starter code:import { Ion, Viewer, Terrain, createOsmBuildingsAsync, Cartesian3, Math, } from "cesium"; import "cesium/Widgets/widgets.css"; import "../src/css/main.css"; // Your access token can be found at: https://cesium.com/ion/tokens. // Ion.defaultAccessToken = "YOUR TOKEN HERE"; // Initialize the Cesium Viewer in the HTML element with the `cesiumContainer` ID. const viewer = new Viewer("cesiumContainer", { terrain: Terrain.fromWorldTerrain(), }); // Add Cesium OSM Buildings, a global 3D buildings layer. const buildingTileset = await createOsmBuildingsAsync(); viewer.scene.primitives.add(buildingTileset); // Fly the camera to San Francisco at the given longitude, latitude, and height. viewer.camera.flyTo({ destination: Cartesian3.fromDegrees(-122.4175, 37.655, 400), orientation: { heading: Math.toRadians(0.0), pitch: Math.toRadians(-15.0), }, });
This code initializes the Cesium Viewer, adds Cesium OSM Buildings to the terrain, and moves the
Camera
to San Francisco. -
Update
index.html
with the CesiumContainer<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> </head> <body> <div id="cesiumContainer"></div> </body> </html>
-
Run the command
npm run build
. Ensure that the project is built correctly. -
Run
npm start
and open http://localhost:8080/ in a web browser to see the CesiumJS viewer.
Feel free to copy and paste your favorite Sandcastle example. For example, many community members enjoy the Cesium OSM Buildings demo.
Webpack can be leveraged in many more ways to increase performance, decrease your bundle size, and perform additional or complex build steps. Here we’ll discuss a few configuration options relevant to using the CesiumJS library.
Source maps allow webpack to trace errors back to the original content. They offer more or less detailed debugging information in exchange for compiling speed. We recommend setting devtool
to the 'eval' option in webpack.config.js
devtool: 'eval'
Please note that source maps are not recommended for production code.
The official cesium-webpack-example repo contains the minimal webpack configuration, the hello world code covered in this tutorial, and instructions for optional code configurations.
Learn CesiumJS with our CesiumJS tutorial and explore Sandcastle demos to see CesiumJS in action.
To learn more about webpack, take a look at the webpack guides, or dive into the API.