Is there a good way to use Cesium with Vite?

I found a 170 stars repo vite-plugin-cesium .
But based on the latest response from the owner in the issues, it seems that this repository has been discontinued.Hi, blogger me has changed industries, so it’s been a while since I last followed Cesium.
Is there an official tutorial on using Vite for development and production builds with CesiumJS?

Not yet, but we have seen a lot of interest. We’re tracking this in Create new simple example with vue2 and vite · Issue #11306 · CesiumGS/cesium · GitHub. Let us know if you have any input!

I found maybe a good solution to solve the problem. Here is the code simply-cesium-vite-vue. Hope it helpful.
Also, I reply on the issue above with more details!
But I am still looking forward to it. If it is possible to run perfectly without any configuration or just by installing an official plugin after installing the Cesium dependency, that would be ideal! Thank you for your efforts!

1 Like

I had moved from webpack to vite to bundle my preact app, but no experience about vue.
Just like in webpack, we can copy the static assets to your build directory
If you need to know something about configuration, we can discuss this. But using vite to bundle frontend is definitely ok.
It’s interesting that we can use vite

alias:{
      "@cesium/widgets": "https://esm.sh/@cesium/widgets@4.1.0", 
      "@cesium/engine": "https://esm.sh/@cesium/engine@5.0.0",
}

so we can use esm CDN and import cesium module like this:

import { Viewer } from '@cesium/widgets'

Hi @cywhale, maybe you can assist - In my app I can work with cesium imports correctly for dev, whereas the build bundle process in Vite throws a breaking error when the app initiates:
‘Cesium is not defined.’

Note that Vite brings the cesium files to the build directory.

Any advice? Many thanks

I’m not sure, maybe I had ever encounter this in my beginning use cesium with webpack. But soon I change the import method so I don’t import the whole Cesium. I can provide my settings about cesium in Vite. But I’m not sure if it can help you. Note that I import cesium from CDN esm, not from npm install.

//package.json
  "devDependencies": {
    "cesium": "1.111.0",
  }
//vite.config.ts
import { viteStaticCopy } from 'vite-plugin-static-copy'

const cesiumSource = "./node_modules/@cesium/engine/Source"
const cesiumWorkers = "../Build/Workers"
const cesiumDest = `${base}` //copy to build/${base}

export default defineConfig({
  build: {
    target: 'esnext', 
    commonjsOptions: {
      transformMixedEsModules: true,
    },
      plugins: [
        nodeResolve({
          moduleDirectories: ['node_modules']
        }),
      ],
      external: ['@cesium'],
    }
  },
  resolve: {
    preserveSymlinks: true, 
    extensions: ['.js', '.mjs', '.jsx', 'ts', 'tsx'],
    mainFields: ['module'],
    alias: {
      "@": resolve(__dirname, "src"),
      "@cesium/widgets": "https://esm.sh/@cesium/widgets@4.3.0"
      "@cesium/engine": "https://esm.sh/@cesium/engine@6.1.0",
    }
  },
  plugins: [
    viteStaticCopy({
      targets: [
        {
          src: resolve(cesiumSource, cesiumWorkers),
          dest: `${cesiumDest}/`
        },
        {
          src: resolve(cesiumSource, "Assets"),
          dest: `${cesiumDest}/`
        },
        {
          src: resolve(cesiumSource, "../../widgets/Source/*"),
          dest: `${cesiumDest}/Widgets/`,
        },
        { src: resolve(cesiumSource, 'ThirdParty'),
          dest: `${cesiumDest}/`,
        }
      ]
    }),
})
//app.jsx
window.CESIUM_BASE_URL = `/${base}/`
//MyComponent.jsx
import { Viewer } from '@cesium/widgets' 
import { Camera, Rectangle } from '@cesium/engine' 
//skip...

And finally, I opened a repo on github to solve this problem. This vite plugin is so fast that takes only 300ms to build in my laptop. It will copy the four folders and externalize Cesium.js, without impact on development. Hope it will be helpful!

Thank you both for your quick assistance.
@s3xysteak is that plugin configured only for the build process? it throws breaking errors in dev mode and in build mode I still get ‘Cesium is not defined’. I have my Vite setup as follows:


import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vitest/config';
import cesium from 'vite-plugin-cesium';
import { buildCesium } from 'vite-plugin-cesium-build'

export default defineConfig(({ command, mode, isSsrBuild, isPreview }) => {
	if (command === 'serve') {
	  return {
		// dev specific config
		plugins: [sveltekit(), cesium()],
		test: {
			include: ['src/**/*.{test,spec}.{js,ts}']
		},
	  }
	} else {
	  // command === 'build'
	  return {
		// build specific config
		plugins: [sveltekit(), buildCesium(
			// Specifies the location of the Cesium package folder
			// Which means the relevant resources of CesiumJS will be obtained from this folder
			//from: 'node_modules/cesium/Build/Cesium',
			// Specifies the location of the built resources
			// Which means the built resources will be placed under /dist/cesium-package/
			//to: 'cesium-package'
		)],
		test: {
			include: ['src/**/*.{test,spec}.{js,ts}']
		},
		ssr: { noExternal: ["@supabase/postgrest-js"] }, // Activate this in build
	  }
	}
  })

Keen to know your thoughts on this. Thanks

It should work correctly automatically in both development mode and build mode. The testing environment is Vite 4.5.0 && Vite 5.0.2, Cesium 1.111.0, with Vue3.3.8 && Vanilla. You can see more details in example folder in the repo of vite-plugin-cesium-build.
Here is a simple example:

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

import { buildCesium } from "vite-plugin-cesium-build";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    buildCesium()
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

You can try:

import { sveltekit } from '@sveltejs/kit/vite'
import { defineConfig } from 'vitest/config'
import { buildCesium } from 'vite-plugin-cesium-build'

export default defineConfig(({ command, mode, isSsrBuild, isPreview }) => {
  if (command === 'serve') {
    return {
      // dev specific config
      plugins: [sveltekit(), buildCesium()],
      test: {
        include: ['src/**/*.{test,spec}.{js,ts}']
      }
    }
  } else {
    // command === 'build'
    return {
      // build specific config
      plugins: [sveltekit(), buildCesium()],
      test: {
        include: ['src/**/*.{test,spec}.{js,ts}']
      },
      ssr: { noExternal: ['@supabase/postgrest-js'] } // Activate this in build
    }
  }
})

Or provide more details about versions of Vite and Cesium.
If it still throw error, I will try start a svelte demo and try to figure out what happened in few days.

1 Like

thank you. It seems as though the cesium is not defined error has now disappeared.

However, these errors still remain and prevent cesium to initiate with either when npm run dev --

or when npm run build and npm run preview :

I installed the ‘vite-plugin-cesium-build’ with:
npm i --save-dev vite-plugin-cesium-build

Relevant tech stack:

  • npm 9.4.2
  • node 20.9.0
  • @sveltejs/kit@1.27.6
  • cesium@1.111.0
  • svelte@4.2.4
  • vite-plugin-cesium-build@0.1.0
  • vite-plugin-cesium@1.2.22
  • vite@4.5.0
  • vitest@0.32.4

Try to add

Object.defineProperty(globalThis, 'CESIUM_BASE_URL', {
  value: '/cesium-package/'
})

before using CesiumJS. I just learn a bit about svelte, and I find it seems no main.js in svelte. In default settings, vite-plugin-cesium-build will add the code above to your main.js or main.ts to set CESIUM_BASE_URL.

It seems to work perfectly in both dev and build configs! thank you so much

You are welcome. I will try to solve that problem. Before that, maybe it should just report a warning when no /src/main.js is detected. I have added the problem in the README.md file.

1 Like

Hi, I’m trying to integrate react-native-web with Cesium and Vite, dependencies in react-native needs optimizeDeps becouse of this error:

[ERROR] The JSX syntax extension is not currently enabled
The esbuild loader for this file is currently set to “js” but it must be set to “jsx” to be able to parse JSX syntax.

When I try to use vite-plugin-cesium-build with optimizeDeps I can see only black screen, any suggestions how to use vite-plugin-cesium-build with optimizeDeps ?

This is my vite.config.ts:

import {defineConfig} from 'vite';
import cesium from 'vite-plugin-cesium-build';

const extensions = [
  '.mjs',
  '.web.tsx',
  '.tsx',
  '.web.ts',
  '.ts',
  '.web.jsx',
  '.jsx',
  '.web.js',
  '.js',
  '.css',
  '.json',
];

export default defineConfig({
  define: {
    global: 'window',
    __DEV__: 'true',
  },

  resolve: {
    extensions,
    alias: [
      {find: 'react-native', replacement: 'react-native-web'},
    ],
  },
  plugins: [cesium()],
  optimizeDeps: {
    esbuildOptions: {
      resolveExtensions: extensions,
      loader: {
        '.js': 'jsx',
      },
    },
  },
  server: {
    port: 3000,
    host: 'localhost',
  },
});

This is my main.js:

import React from 'react';
import * as Cesium from 'cesium';
import 'cesium/Build/Cesium/Widgets/widgets.css';

const app = document.querySelector('#root');

const viewer = new Cesium.Viewer(app);

viewer.camera.flyTo({
  destination: Cesium.Cartesian3.fromDegrees(120, 31.8, 100000),
});

Since version 0.2.1, CESIUM_BASE_URL will be set in index.html, which should provide the best compatibility.

The above issue was caused by React not having a default “main.js” file (instead, it uses “main.jsx”), which has been addressed in the repository’s issue.
If any other similar errors occur, you can still use this solution:

// vite.config.js
export default defineConfig({
  plugins: [cesium({ customCesiumBaseUrl: true })]
})

// main.js, main.jsx or any other file
Object.defineProperty(globalThis, 'CESIUM_BASE_URL', {
  // `/cesium-package/` is the default path
  value: '/cesium-package/'
})

For more issues related to this plugin, please raise them in the issues of the plugin repository to avoid disturbing other users in the Cesium Community :pray:.

Hi s3xysteak! I am trying to implement your solution on my vue+vite+Laravel 11 project. I have installed cesium and your cesium-plugin. I got a lot of error messages, mainly dealing with wrong asset-paths and cross domain issues between Vite and Laravel dev servers. I ended up with error 404 on everything under /node_modules/cesium/Build in the console at page loading:
“GET http://localhost:8000/node_modules/cesium/Build/Cesium/… net::ERR_ABORTED 404 (Not Found)”
The files are all inside /node_modules/cesium/Build/Cesium/…
I am a bit confuse about the right place to set cesium’s base url. I have tried to put it within the plugin on vite.config:
cesium({
from: ‘node_modules/cesium/Build/Cesium’,
to: ‘cesium-package’,
customCesiumBaseUrl: false
})
And also within my vue file:
Cesium.buildModuleUrl.setBaseUrl(‘/node_modules/cesium/Build/Cesium/’);
But it seems both settings are ignored.
Any idea whare do I go wrong?
Thanks in advance :slight_smile:

Could you open a issue in the github repo for me to track the problem?

Actually there are no settings required by default cesium(), you can see the demo folder in the github repo. Could you provide more details like error messages or network in f12 console?