Skip to content

Installation

Install cesium and resium:

Terminal window
npm install --save cesium resium
# OR
yarn add cesium resium

Cesium ships a large set of static assets (web workers, third-party libraries, widget styles, and so on) that must be served alongside your app. How you wire those up depends on your bundler:

When you finish set up, you can import Cesium:

import { Cartesian3 } from "cesium";

Then advance to Getting Started.

Vite is the recommended way to use Resium. vite-plugin-cesium copies Cesium’s static assets and sets CESIUM_BASE_URL for you, so there is almost nothing to configure.

See also: example project

Create a new Vite project (select the ā€œreactā€ template):

Terminal window
npm create vite@latest example -- --template react
# OR
yarn create vite example --template react

Then install Cesium, Resium, and vite-plugin-cesium:

Terminal window
npm install --save cesium resium
npm install --save-dev vite-plugin-cesium
# OR
yarn add cesium resium
yarn add --dev vite-plugin-cesium

Then edit vite.config.js:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import cesium from "vite-plugin-cesium";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), cesium()],
});

That’s all!

See also: example project (App Router)

We assume your Next.js project (App Router) already exists. Cesium runs only in the browser, so it has to be loaded client-side with its static assets served from /public.

Cesium loads its built assets (workers, third-party libraries, widget images) at runtime, so they have to be served from /public. Add a postinstall script that copies them into public/cesium on every install, then ignore the copy in git:

package.json
{
"scripts": {
"postinstall": "node -e \"require('fs').cpSync('node_modules/cesium/Build/Cesium','public/cesium',{recursive:true})\""
}
}
Terminal window
npm install
# OR
yarn
.gitignore
/public/cesium

Make a Client Component, import the widgets CSS directly, and point Cesium at the copied assets via window.CESIUM_BASE_URL:

app/Cesium.js
"use client";
import "cesium/Build/Cesium/Widgets/widgets.css";
import { Viewer } from "resium";
// Cesium loads its workers/assets relative to this URL (copied to /public/cesium above).
window.CESIUM_BASE_URL = "/cesium";
export default function Cesium() {
return <Viewer full />;
}

In the App Router, dynamic(..., { ssr: false }) is only allowed inside a Client Component, so render it from a client page:

app/page.js
"use client";
import dynamic from "next/dynamic";
const Cesium = dynamic(() => import("./Cesium"), { ssr: false });
export default function Page() {
return <Cesium />;
}

That’s all!

If you are still on the Pages Router, the same idea applies — import the widgets CSS in _app, set window.CESIUM_BASE_URL in the client-only component, and disable SSR with next/dynamic:

pages/_app.js
import "cesium/Build/Cesium/Widgets/widgets.css";
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />;
}
components/Cesium.js
import { Viewer } from "resium";
window.CESIUM_BASE_URL = "/cesium";
export default function Cesium() {
return <Viewer full />;
}
pages/index.js
import dynamic from "next/dynamic";
const Cesium = dynamic(() => import("../components/Cesium"), { ssr: false });
export default function Home() {
return <Cesium />;
}

There are two approaches. Choose one.

Option A: Copy whole Cesium files and load Cesium in HTML

Section titled ā€œOption A: Copy whole Cesium files and load Cesium in HTMLā€

See also: example project

Terminal window
npm install --save-dev copy-webpack-plugin html-webpack-plugin html-webpack-tags-plugin
# OR
yarn add copy-webpack-plugin html-webpack-plugin html-webpack-tags-plugin

Then, edit your webpack configuration.

Cesium will be loaded in HTML. Notify it to webpack.

{
externals: {
cesium: "Cesium";
}
}

When cesium is loaded, webpack uses window.Cesium instead of loading source files.

  • Copy whole Cesium files at build time with copy-webpack-plugin
  • Add tags to index.html to load JS and CSS with html-webpack-tags-plugin
  • Notify Cesium to its path with webpack define plugin
const webpack = require("webpack");
const HtmlPlugin = require("html-webpack-plugin");
const HtmlTagsPlugin = require("html-webpack-tags-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
{
plugins: [
// ...
new CopyWebpackPlugin({
patterns: [
{
from: "node_modules/cesium/Build/Cesium",
to: "cesium",
},
],
}),
new HtmlPlugin({
template: "index.html",
}),
new HtmlTagsPlugin({
append: false,
tags: ["cesium/Widgets/widgets.css", "cesium/Cesium.js"],
}),
new webpack.DefinePlugin({
CESIUM_BASE_URL: JSON.stringify("/cesium"),
}),
];
}

Note: If publicPath in webpack config is changed, CESIUM_BASE_URL may have to be changed also.

Option B: Copy only asset files and bundle Cesium normaly except assets

Section titled ā€œOption B: Copy only asset files and bundle Cesium normaly except assetsā€

In this way, imported and used Cesium source codes are bundled to your app’s source code with webpack.

See also: example project and Cesium official example

Terminal window
npm install --save-dev html-webpack-plugin copy-webpack-plugin css-loader style-loader url-loader
# OR
yarn add --dev html-webpack-plugin copy-webpack-plugin css-loader style-loader url-loader

Then, edit your webpack configuration.

  • Copy only asset files at build time
  • Cesium refers to CESIUM_BASE_URL to find asset files
const webpack = require("webpack");
const HtmlPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
{
plugins: [
new HtmlPlugin({
template: "index.html",
}),
new CopyWebpackPlugin({
patterns: [
{ from: "node_modules/cesium/Build/Cesium/Workers", to: "Workers" },
{
from: "node_modules/cesium/Build/Cesium/ThirdParty",
to: "ThirdParty",
},
{ from: "node_modules/cesium/Build/Cesium/Assets", to: "Assets" },
{ from: "node_modules/cesium/Build/Cesium/Widgets", to: "Widgets" },
],
}),
new webpack.DefinePlugin({
CESIUM_BASE_URL: JSON.stringify(""),
}),
];
}

Note: If publicPath in webpack config is changed, CESIUM_BASE_URL may have to be changed also.

{
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: "babel-loader",
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|gif|jpg|jpeg|svg|xml|json)$/,
use: ["url-loader"],
},
];
}
}

Add a link tag in head of your index.html to load CSS:

<link rel="stylesheet" href="/Widgets/widgets.css" />

Note: if you have changed CESIUM_BASE_URL, you may also have to change this.

Tips: Using html-webpack-tags-plugin is also OK!

The monolithic cesium package is just a thin re-export of the modular @cesium/engine and @cesium/widgets packages. Resium imports everything from "cesium" and leaves that import external in its build, so you can depend on the modular packages directly by aliasing "cesium" to them — no changes to Resium are required.

Install the packages and create a small module that re-exports both:

Terminal window
# with <Viewer>
npm install --save @cesium/engine @cesium/widgets resium
# engine-only (use <CesiumWidget> instead of <Viewer>)
npm install --save @cesium/engine resium
src/cesium.ts
export * from "@cesium/engine";
export * from "@cesium/widgets"; // omit this line for an engine-only (no <Viewer>) setup

Mirror the alias in tsconfig.json so TypeScript resolves cesium the same way the bundler does:

tsconfig.json
{
"compilerOptions": {
"paths": {
"cesium": ["./src/cesium.ts"]
}
}
}

The bundler-side alias is shown in the full configs below.

vite-plugin-cesium can not be used here — it copies from node_modules/cesium. With the modular packages the static assets live in different places, so copy them yourself and tell Cesium where they are via CESIUM_BASE_URL:

WhatSource (modular packages)
Workers@cesium/engine/Build/Workers
ThirdParty@cesium/engine/Build/ThirdParty
Assets@cesium/engine/Source/Assets
Widgets CSS@cesium/widgets/Source/widgets.css

Vite (using vite-plugin-static-copy):

vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { viteStaticCopy } from "vite-plugin-static-copy";
export default defineConfig({
define: {
// where the copied assets are served from
CESIUM_BASE_URL: JSON.stringify("/cesium"),
},
resolve: {
alias: { cesium: "/src/cesium.ts" },
},
plugins: [
react(),
viteStaticCopy({
targets: [
{ src: "node_modules/@cesium/engine/Build/Workers", dest: "cesium" },
{ src: "node_modules/@cesium/engine/Build/ThirdParty", dest: "cesium" },
{ src: "node_modules/@cesium/engine/Source/Assets", dest: "cesium" },
],
}),
],
});

webpack (using copy-webpack-plugin):

webpack.config.js
const path = require("path");
const webpack = require("webpack");
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
resolve: {
alias: { cesium: path.resolve(__dirname, "src/cesium.ts") },
},
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: "node_modules/@cesium/engine/Build/Workers", to: "cesium/Workers" },
{ from: "node_modules/@cesium/engine/Build/ThirdParty", to: "cesium/ThirdParty" },
{ from: "node_modules/@cesium/engine/Source/Assets", to: "cesium/Assets" },
],
}),
new webpack.DefinePlugin({
CESIUM_BASE_URL: JSON.stringify("/cesium"),
}),
],
};

The <Viewer> UI needs the widgets stylesheet. Import it once in your app entry (the bundler resolves it from the package):

import "@cesium/widgets/Source/widgets.css";

Skip this step entirely for an engine-only (<CesiumWidget>) setup.