I’ve already successfully built a Cesium app using webpack as outlined inthe following Cesium tutorial:
This tutorial explains how to integrate the Cesium npm module from webpack, and explores more advanced webpack configurations for optimizing an application using CesiumJS. – Cesium
I’m now trying to create a similar app using Vue.js. Currently I’m unable to get the Vue.js app to run or build due to the following error:
ERROR ReferenceError: path is not defined
ReferenceError: path is not defined
at Object.<anonymous> (C:\Users\virt\Documents\GitHub_Repositories\Websites\Vue_Cesium_Client\vue_cesium_client\vue.config.js:19:11)
at Module._compile (node:internal/modules/cjs/loader:1105:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at exports.loadModule (C:\Users\virt\Documents\GitHub_Repositories\Websites\Vue_Cesium_Client\vue_cesium_client\node_modules\@vue\cli-shared-utils\lib\module.js:86:14)
at loadFileConfig (C:\Users\virt\Documents\GitHub_Repositories\Websites\Vue_Cesium_Client\vue_cesium_client\node_modules\@vue\cli-service\lib\util\loadFileConfig.js:30:20)
at Service.loadUserOptions (C:\Users\virt\Documents\GitHub_Repositories\Websites\Vue_Cesium_Client\vue_cesium_client\node_modules\@vue\cli-service\lib\Service.js:339:44)
PS C:\Users\virt\Documents\GitHub_Repositories\Websites\Vue_Cesium_Client\vue_cesium_client>
Steps to recreate:
Install Node.js
Use NPM to insall the VUE CLI:
npm install -g @vue/cli
Create a directory for the project.
Navigate to the project folder.
Create the Vue project:
vue create <project name>
Select option ‘Manually select features’.
Select ‘Babel’ and deselect ‘Linter/Formatter’ by pressing Space Bar
and then Return
.
Select Vue ‘3.x’.
Select to place Babel ‘In dedicated config files’.
Enter ‘N’ when prompted to save preset for future projects.
Open the project folder in your preferred IDE (e.g. code .
for VSCode from the command line).
Navigate to the newly created app folder:
cd <project_name>
Install the Cesium module from npm and add it to package.json:
npm install --save-dev cesium
Test the build command
npm run build
Run the development server:
npm run serve
Add the following to the top of vue.config.js:
const { defineConfig } = require("@vue/cli-service");
// The path to the CesiumJS source code
const cesiumSource = 'node_modules/cesium/Source';
const cesiumWorkers = '../Build/Cesium/Workers';
Update the module.exports
section in vue.config.js as follows:
module.exports = defineConfig({
transpileDependencies: true,
context: __dirname,
entry: {
app: "./src/main.js",
output: {
filename: "[name].js",
path: path.resolve(__dirname, "dist"),
// Add module rules for loading CSS and other files
module: {
rules: [
test: /\.css$/,
use: ["style-loader", "css-loader"],
test: /\.(png|gif|jpg|jpeg|svg|xml|json)$/,
use: ["url-loader"],
// Address Webpack compilation issues of Cesium
output: {
filename: "[name].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,
// Add a Cesium alias that can be referenced in app code
resolve: {
alias: {
// CesiumJS module name
cesium: path.resolve(__dirname, cesiumSource),
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(""),
new Dotenv(),
Rerun the development server:
npm run serve
.
My assumption is that the vue.config.js file should accept the webpack configuration but I’m unsure how to implement this properly. Vue provide the following guidance ( Working with Webpack | Vue CLI ) but I’m unclear how that applies in this instance. Any advice appreciated.
Hi @virtualarchitectures,
I was able to get CesiumJS up and running in a Vue app by following these steps:
Install the following dependencies:
npm i cesium # This should be a dependency, not a devDependency
npm i --save-dev copy-webpack-plugin
npm i --save-dev webpack
Configure your vue.config.js
file as follows:
const { defineConfig } = require("@vue/cli-service");
const path = require("path"); // Not importing the builtin-path module was causing your build failure.
const CopyWebpackPlugin = require("copy-webpack-plugin");
const { DefinePlugin } = require("webpack");
const cesiumSource = "node_modules/cesium/Source";
const cesiumWorkers = "../Build/Cesium/Workers";
module.exports = defineConfig({
transpileDependencies: true,
configureWebpack: {
resolve: {
fallback: { https: false, zlib: false, http: false, url: false },
plugins: [
new DefinePlugin({
CESIUM_BASE_URL: JSON.stringify(""),
new CopyWebpackPlugin({
patterns: [
{ from: path.join(cesiumSource, "Assets"), to: "Assets" },
{ from: path.join(cesiumSource, "ThirdParty"), to: "ThirdParty" },
{ from: path.join(cesiumSource, "Widgets"), to: "Widgets" },
{ from: path.join(cesiumSource, cesiumWorkers), to: "Workers" },
Add a new CesiumViewer.vue
component:
<script>
import { Viewer } from "cesium";
import "cesium/Source/Widgets/widgets.css";
const viewer = new Viewer("app");
viewer.scene.debugShowFramesPerSecond = true;
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#cesium-container {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
</style>
Edit your App.vue
component to use the CesiumViewer.vue
component:
<template>
<div id="cesium-container">
<CesiumViewer />
</template>
<script>
import CesiumViewer from "./components/CesiumViewer.vue";
export default {
name: "App",
components: {
CesiumViewer,
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
</style>
Once you run npm run serve
, everything should work:
Hope this helps,
Hi @sanjeetsuhag That was super helpful. The steps you outlined get the globe onscreen but I’m still having difficulty recreating my app. I’m trying to pull resources from Cesium ION but I’m having difficulty initializing the viewer (and yes…I have checked my token is valid ).
<script>
import Cesium from 'cesium/Source/Cesium';
//import { Viewer } from "cesium";
import "cesium/Source/Widgets/widgets.css";
// Reference to access token
Cesium.Ion.defaultAccessToken = '<TOKEN>';
// Initialize the Cesium Viewer in the HTML element with the ID.
const viewer = new Cesium.Viewer("app", {
timeline: false,
animation: false,
baseLayerPicker: false,
geocoder: false,
const buildingsTileset = viewer.scene.primitives.add(Cesium.createOsmBuildings());
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(-104.9965, 39.74248, 4000)
//const viewer = new Viewer("app");
viewer.scene.debugShowFramesPerSecond = true;
</script>
Currently I get the following error:
Uncaught TypeError: Cannot read properties of undefined (reading 'Ion')
at eval (CesiumViewer.vue?a500:7:1)
at ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/CesiumViewer.vue?vue&type=script&lang=js (app.js:30:1)
at __webpack_require__ (app.js:217:33)
at fn (app.js:515:21)
at eval (CesiumViewer.vue?vue&type=script&lang=js:5:215)
at ./src/components/CesiumViewer.vue?vue&type=script&lang=js (app.js:118:1)
at __webpack_require__ (app.js:217:33)
at fn (app.js:515:21)
at eval (CesiumViewer.vue:2:99)
at ./src/components/CesiumViewer.vue (app.js:96:1)
I think the reference to ION in the error may be a red herring. If I remove the reference to Cesium.Ion.defaultAccessToken
the error I get refers to the ‘Viewer’:
app.js:220 Uncaught TypeError: Cannot read properties of undefined (reading 'Viewer')
at eval (CesiumViewer.vue?a500:10:1)
at ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/CesiumViewer.vue?vue&type=script&lang=js (app.js:30:1)
at __webpack_require__ (app.js:217:33)
at fn (app.js:515:21)
at eval (CesiumViewer.vue?vue&type=script&lang=js:5:215)
at ./src/components/CesiumViewer.vue?vue&type=script&lang=js (app.js:118:1)
at __webpack_require__ (app.js:217:33)
at fn (app.js:515:21)
at eval (CesiumViewer.vue:2:99)
at ./src/components/CesiumViewer.vue (app.js:96:1)
Is the reference import Cesium from 'cesium/Source/Cesium';
I added in the top of the script correct (derived from ES6 style import here: This tutorial explains how to integrate the Cesium npm module from webpack, and explores more advanced webpack configurations for optimizing an application using CesiumJS. – Cesium)? Do I need something additional in my vue.config.js
?
Many thanks!
@virtualarchitectures The tutorial you referenced is outdated, unfortunately. You should import modules from the cesium
package like this:
import { Ion, Viewer } from "cesium";
Sorry @sanjeetsuhag but that doesn’t seem to be working. Is still get the error ‘Cesium is not defined’. VSCode is indicating that the import declarations are unused despite my referencing Cesium.Ion.defaultAccessToken=
and const viewer = new Cesium.Viewer()
.
Changing the above references to Ion.defaultAccessToken=
and Viewer()
by removing ‘Cesium’ allows the me to serve the app, but doesn’t load the resources from Cesium Ion and still gives the ‘Cesium not defined’ error.
I can successfully import everything using import * as Cesium from "cesium";
instead. This works but I’d rather be importing just what’s needed for my build. I’ve poked about on GitHub but didn’t spot anything relevant. If there is any particular documentation or up-to-date examples you could point me to to help me understand the changes that would be much appreciated. It’s basically the boilerplate stuff that is giving me the headache I’m afraid.
@virtualarchitectures When importing modules directly you don’t need to prefix them with the Cesuim.
. For example,
Cesium.Ion.defaultAccessToken = '0';
should instead be:
import { Ion } from "cesium";
Ion.defaultAccessToken = '0';
but doesn’t load the resources from Cesium Ion and still gives the ‘Cesium not defined’ error.
Can you describe what the error is? Are you using the Cesium.
anywhere else in your app?
In case it helps, here’s what the source code you posted above should look like:
<script>
import {
Cartesian3,
createOsmBuildings,
Viewer
} from "cesium";
import "cesium/Source/Widgets/widgets.css";
// Reference to access token
Ion.defaultAccessToken = '<TOKEN>';
// Initialize the Cesium Viewer in the HTML element with the ID.
const viewer = new Viewer("app", {
timeline: false,
animation: false,
baseLayerPicker: false,
geocoder: false,
const buildingsTileset = viewer.scene.primitives.add(createOsmBuildings());
viewer.camera.flyTo({
destination: Cartesian3.fromDegrees(-104.9965, 39.74248, 4000)
viewer.scene.debugShowFramesPerSecond = true;
</script>
Hi @sanjeetsuhag I realised that I was using the Cesium alias elsewhere where I had been calling Cesium3DTileSet()
, IonResource.fromAssetId()
, Cartesian3()
and Math()
. If I remove the preceding references I had to Cesium.
and import each namespace or class separately the app serves successfully but still errors in the browser before loading my tileset or moving the camera.
Probably better that I share some of my actual code rather than the boilderplate example to avoid confusion:
<script>
//import * as Cesium from "cesium";
import { Ion, Viewer, IonResource, Cesium3DTileset, Cartesian3, Math } from "cesium";
import "cesium/Source/Widgets/widgets.css";
// Reference to access token
Ion.defaultAccessToken = '<My Token>';
// Initialize the Cesium Viewer in the HTML element with the "app" ID.
const viewer = new Viewer("app", {
timeline: false,
animation: false,
baseLayerPicker: false,
geocoder: false,
//------------------------3DTilesets------------------------//
const tileset = <My Tileset>;
const buildings = viewer.scene.primitives.add(
new Cesium3DTileset({
url: IonResource.fromAssetId(tileset),
//------------------------Camera------------------------//
tileset.readyPromise.then(function () {
viewer.camera
.flyTo({
destination: Cartesian3.fromDegrees(-0.0970234, 51.3623602, 600),
orientation: {
heading: Math.toRadians(0.0),
pitch: Math.toRadians(-20.0),
.otherwise(function (error) {
console.log(error);
</script>
The error in the broswer console refers to undefined properties:
app.js:220 Uncaught TypeError: Cannot read properties of undefined (reading 'then')
at eval (CesiumViewer.vue?a500:29:1)
at ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/CesiumViewer.vue?vue&type=script&lang=js (app.js:30:1)
at __webpack_require__ (app.js:217:33)
at fn (app.js:515:21)
at eval (CesiumViewer.vue?vue&type=script&lang=js:5:215)
at ./src/components/CesiumViewer.vue?vue&type=script&lang=js (app.js:118:1)
at __webpack_require__ (app.js:217:33)
at fn (app.js:515:21)
at eval (CesiumViewer.vue:2:99)
at ./src/components/CesiumViewer.vue (app.js:96:1)
That refers to webpack. In VSCode the terminal also provides the following warning in case it is relevant:
warning in ./src/components/CesiumViewer.vue?vue&type=script&lang=js
export 'default' (reexported as 'default') was not found in '-!../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./CesiumViewer.vue?vue&type=script&lang=js' (module has no exports)
My feelings are there’s something wrong with my reference to Ion
and/or there’s an issue with my vue.config.js
which I assume is sent to webpack. The config file is currently an exact match for the one you’d provided above as is the App.vue
so there should be no probs there.
My package.json
is as follows in case there are any version issue:
"name": "vue_cesium_client",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
"dependencies": {
"cesium": "^1.99.0",
"core-js": "^3.8.3",
"vue": "^3.2.13"
"devDependencies": {
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"copy-webpack-plugin": "^11.0.0",
"dotenv-webpack": "^8.0.1",
"webpack": "^5.74.0"
Apologies for making a meal of it but I’m very confused. If necessary I can go with the import all option. However, it would be really cool to see a Cesium guide or blogpost for Vuejs though.
@virtualarchitectures From the code sample you posted above, it seems like the tileset
variable is a number that contains the asset ID for the tileset hosted on Cesium ion. You’re then calling tileset.readyPromise.then
which seems to be the source of the error. I believe that should be corrected to buildings.readyPromise.then
since the buildings
variable is the actual Cesium3DTileset
.
Should I ask another question about Cesium to run in Vue.js APP?
In my case, I followed this demo code that it was success.
But, when I import a KML file from this project of folder which always get an error message.
Here is my code and my kml file.
CesiumViewer.vue
import * as Cesium from "cesium"
import "cesium/Source/Widgets/widgets.css";
const viewer = new Cesium.Viewer('app')
viewer.scene.debugShowFramesPerSecond = true
viewer.dataSources.add(Cesium.KmlDataSource.load('../SampleData/demo.kml',
camera: viewer.scene.camera,
canvas: viewer.scene.canvas
package.json
"name": "vue-cesium",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
"dependencies": {
"cesium": "^1.100.0",
"core-js": "^3.8.3",
"vue": "^3.2.13"
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"copy-webpack-plugin": "^9.1.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"webpack": "^5.75.0"
"eslintConfig": {
"root": true,
"env": {
"node": true
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended"
"parserOptions": {
"parser": "@babel/eslint-parser"
"rules": {}
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"not ie 11"
Tree Commend
KML File
demo.kml (336.8 KB)
Does Cesium is not support KmlDataSource to load KML file in vue framework?
Or here are some mistake of setting in my project?
Thank you for your anwser.
You’ll need to ensure your asset files are getting served. Static asset files, like KML, aren’t bundled into your JavaScript, so you’ll need to handle them seperately.
Usually, you can use the copy-webpack-plugin
to copy them over to your build directory and serve them in your app.
Hi, I have followed the guide and now I’m getting those errors:
ERROR in node:url
Module build failed: UnhandledSchemeError: Reading from “node:url” is not handled by plugins (Unhandled scheme).
Webpack supports “data:” and “file:” URIs by default.
You may need an additional plugin to handle “node:” URIs.