Getting Cesium to work with Angular 7

1. A concise explanation of the problem you're experiencing.

I have followed many online guides in an attempt to get Cesium to work in a web application built on Angular 7 + Java Spring (e.g. https://www.npmjs.com/package/angular-cesium). But in my browser console, I get the following error:

Uncaught ReferenceError: Cesium is not defined
    at eval (webpack-internal:///./node_modules/primitive-primitives/dist/main.js:464)
    at Object.eval (webpack-internal:///./node_modules/primitive-primitives/dist/main.js:468)
    at __webpack_require__ (webpack-internal:///./node_modules/primitive-primitives/dist/main.js:25)
    at Object.eval (webpack-internal:///./node_modules/primitive-primitives/dist/main.js:106)
    at __webpack_require__ (webpack-internal:///./node_modules/primitive-primitives/dist/main.js:25)
    at Object.eval (webpack-internal:///./node_modules/primitive-primitives/dist/main.js:555)
    at __webpack_require__ (webpack-internal:///./node_modules/primitive-primitives/dist/main.js:25)
    at eval (webpack-internal:///./node_modules/primitive-primitives/dist/main.js:69)
    at eval (webpack-internal:///./node_modules/primitive-primitives/dist/main.js:72)
    at webpackUniversalModuleDefinition (webpack-internal:///./node_modules/primitive-primitives/dist/main.js:3)

2. A minimal code example. If you've found a bug, this helps us reproduce and repair it.

The typeRoots array in my tsconfig includes "src/typings.d.ts", which includes "declare var Cesium;", but in my app.main.ts, Cesium is undefined here:

Cesium.buildModuleUrl.setBaseUrl('/assets/cesium/');

Even though WebStorm can navigate with a command+click between app.main.ts and src/typings.d.ts, so I know there is no typo. For reference, my app.module.ts includes:

import { AngularCesiumModule } from 'angular-cesium';

and the following in the provided array:

AngularCesiumModule.forRoot()

I have confirmed that I've run `npm install --save angular-cesium` and `npm install --save cesium`. I've updated angular.json with the assets, styles, and scripts arrays, though the syntax post-angular-cli.json is new:

"architect": {
        "build": {
          "options": {
            "assets": [
              {
                "glob": "**/*",
                "input": "./node_modules/cesium/Build/Cesium",
                "output": "./assets/cesium"
              }
            ],
            "styles": [
              "./node_modules/cesium/Build/Cesium/Widgets/widgets.css"
            ],
            "scripts": [
              "./node_modules/cesium/Build/Cesium/Cesium.js"
            ]
          }
        }
      }

3. Context. Why do you need to do this? We might know a better way to accomplish your goal.

I need to put bar graphs on a globe.

4. The Cesium version you're using, your operating system and browser.

cesium: "^1.59.0",
angular-cesium: "0.0.56",
angular 7.2.12
The application is deployed locally (Mac, sometimes Dockerized environment with Linux) and to Heroku and AWS. The environment doesn't affect the bug.

Hey there,

Do you get the error during build of the project or runtime?

Thank you for getting back to me! I get it during build (e.g. with `npm start`).

Do you use Angular CLI for building your project or some other bundle tool?

I use Angular CLI and jHipster.

It looks like an issue with the build process (the CLI does not seem to injecting the Cesium.js file during building the project). You can try the following:

  1. Ensure that the Cesium.js file is included as a script in your page.
  2. Check out this sample project https://github.com/Developer-Plexscape/cesium-angular-example that works with Angular7 and on wards

Thank you for that! I will give both suggestions a try today and report back with the results. Once the puzzle is solved, I'll write up the step-by-step of what was done :slight_smile:

Sure! You can also follow this blog post https://cesium.com/blog/2018/03/12/cesium-and-angular/ that accompanies the sample project. It has been written for Angular 5 initially but it’s pretty much the same. :slight_smile:

As far as procedure is concerned, bear in mind that Angular Cesium will include schematics in the next version. That is, when someone wants to add angular-cesium library in its Angular CLI project and executes

ng add angular-cesium

``

the library will scaffold its project and fill all the missing pieces (include Cesium assets, Javascript and CSS files) eliminating boilerplate from the user. Here is the relevant issue https://github.com/articodeltd/angular-cesium/issues/267 if you want to follow along.

Great resources! I now realize I’ve run into your great work several times while searching high and low for a solution to my problem. Thank you for helping the rest of us use Cesium!

I can get Cesium working in a vanilla, from-the-ground-up Angular 7 project, but not in my existing jHipster 6.0-generated one. I’ve looked closely at the differences between a working project and my own, and I’ve quadruple checked the helpful resources you’ve sent, and I still have not been able to fix my problem. The problem seems to come down to Cesium not being defined either in a directive or in main.ts. For example, in my cesium directive and in my main.ts, Cesium is undefined:

const viewer = new Cesium.Viewer(this.el.nativeElement); // Cesium directive's ngOnInit()
Cesium.buildModuleUrl.setBaseUrl('/assets/cesium/'); // app.main.ts, before platformBrowserDynamic(). `window['CESIUM_BASE_URL'] = '/assets/cesium/'` also does not work

WebStorm will allow me to click on Cesium and take me to its declaration in angular-cesium or in my typings.d.ts file, so I know I don’t have a typo but something wrong on a deeper level. I checked to see if Cesium.js is loaded on my page, and it appears NOT to be, making me think something might be wrong with my angular.json even though it looks correct:

"architect": {
  "build": {
    "builder": "@angular-devkit/build-angular:browser",
    "options": {
      "index": "src/main/webapp/index.html",
      "assets": [
        "src/main/webapp/favicon.ico",
        "src/main/webapp/assets",
        {
          "glob": "**/*",
          "input": "node_modules/cesium/Build/Cesium",
          "output": "assets/cesium"
        }
      ],
      "styles": ["node_modules/cesium/Build/Cesium/Widgets/widgets.css"],
      "scripts": ["node_modules/cesium/Build/Cesium/Cesium.js"]
    }
  }
}

I tried forcing the issue by loading Cesium.js in index.html before the close of , and I see the script in my document, but still no luck.

I can workaround these errors by putting typings.d.ts in the include array in my tsconfig.json, but of course, this just delays the problem. Everything will compile and run fine, but there won’t be a Cesium map appear where I put with connection to the cesium directive. Also, if I put AngularCesiumModule.forRoot() in my app.module.ts’s imports array, Cesium will be undefined here in browser’s main.js at build time:

EllipsePrimitive.borderStyleToPrimitiveType = {

    solid: Cesium.PrimitiveType.LINE_LOOP,

    dashed: Cesium.PrimitiveType.LINES

};

Any help at all with this tough problem is (and has been) much appreciated. And of course, I’ll be following that PR you put up and any future release!

Thanks very much for your kind words and appreciation.

Is it possible to share part of your code, especially the configuration bits such as an angular.json and package.json ? If you could even upload your front end code to a repository, except for the actual source code files, that would also be great.

Of course! I created a public GitHub repo that replicates my basic project setup and error. This way if the problem gets solved, the repo can help out others:

https://github.com/mplawley/jhipster-cesium-template

I’m really excited to narrow in on a solution! Thank you again for your generous help and advice.

(I have a CesiumViewer under the Entities element of the navbar.)

Hi Mark,

I checked your repository and it seems that you are using custom webpack configuration to build your project and not relying on the built-in provided from the Angular CLI. Check out this article https://cesium.com/docs/tutorials/cesium-and-webpack/ that describes how to add CesiumJS in a webpack application.

Thank you for looking at the repo! I went through that tutorial and, now that I’ve learned webpack must be the problem, pushed harder than I did with that tutorial in the past. I think I’m closer with commit
edc6edea0818f0384480ead2068948516a5d500a because it seems like code from Cesium.js is loaded upon npm start. But npm start also gives me this show-stopping error:


ReferenceError: document is not defined

    at t (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/cesium/Build/Cesium/Cesium.js:544:25177)

    at new te (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/cesium/Build/Cesium/Cesium.js:561:11749)

    at Object.<anonymous> (/Users/marklawley/Developer/jhipster-cesium-template/webpack/webpack.common.js:9:14)

    at Module._compile (internal/modules/cjs/loader.js:688:30)

    at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)

    at Module.load (internal/modules/cjs/loader.js:598:32)

    at tryModuleLoad (internal/modules/cjs/loader.js:537:12)

    at Function.Module._load (internal/modules/cjs/loader.js:529:3)

    at Module.require (internal/modules/cjs/loader.js:636:17)

    at require (internal/modules/cjs/helpers.js:20:18)

    at Object.<anonymous> (/Users/marklawley/Developer/jhipster-cesium-template/webpack/webpack.dev.js:13:22)

    at Module._compile (internal/modules/cjs/loader.js:688:30)

    at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)

    at Module.load (internal/modules/cjs/loader.js:598:32)

    at tryModuleLoad (internal/modules/cjs/loader.js:537:12)

    at Function.Module._load (internal/modules/cjs/loader.js:529:3)

Maybe I made a mistake somewhere? I can’t seem to find it. Or maybe it’s that some things in the docs differ from what I see in my webpack config files. For instance, docs say to import via

var Cesium = require('cesium/Cesium');

But it seems like we must instead do:

var Cesium = require('cesium/Build/Cesium/Cesium.js');

Perhaps I have that in the wrong place?

I think I may have finally gotten it! At the very least, the project is building. The piece I kept missing in past attempts was modifying my vendor.ts file appropriately. npm start finally passes, and now let me see if I can load the cesiumViewer itself in a page. Happy with this progress :slight_smile:

Ah, sadness, I spoke too soon. Upon a webpack build or npm start, actually:

ReferenceError: document is not defined

at t (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/cesium/Build/Cesium/Cesium.js:544:25177)

at new te (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/cesium/Build/Cesium/Cesium.js:561:11749)

at Object.<anonymous> (/Users/marklawley/Developer/jhipster-cesium-template/webpack/webpack.common.js:9:14)

at Module._compile (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/v8-compile-cache/v8-compile-cache.js:192:30)

at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)

at Module.load (internal/modules/cjs/loader.js:598:32)

at tryModuleLoad (internal/modules/cjs/loader.js:537:12)

at Function.Module._load (internal/modules/cjs/loader.js:529:3)

at Module.require (internal/modules/cjs/loader.js:636:17)

at require (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/v8-compile-cache/v8-compile-cache.js:161:20)

at Object.<anonymous> (/Users/marklawley/Developer/jhipster-cesium-template/webpack/webpack.dev.js:13:22)

at Module._compile (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/v8-compile-cache/v8-compile-cache.js:192:30)

at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)

at Module.load (internal/modules/cjs/loader.js:598:32)

at tryModuleLoad (internal/modules/cjs/loader.js:537:12)

at Function.Module._load (internal/modules/cjs/loader.js:529:3)

at Module.require (internal/modules/cjs/loader.js:636:17)

at require (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/v8-compile-cache/v8-compile-cache.js:161:20)

at WEBPACK_OPTIONS (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/webpack-cli/bin/utils/convert-argv.js:116:13)

at requireConfig (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/webpack-cli/bin/utils/convert-argv.js:118:6)

at /Users/marklawley/Developer/jhipster-cesium-template/node_modules/webpack-cli/bin/utils/convert-argv.js:125:17

at Array.forEach (<anonymous>)

at module.exports (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/webpack-cli/bin/utils/convert-argv.js:123:15)

at yargs.parse (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/webpack-cli/bin/cli.js:71:45)

at Object.parse (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/webpack-cli/node_modules/yargs/yargs.js:567:18)

at /Users/marklawley/Developer/jhipster-cesium-template/node_modules/webpack-cli/bin/cli.js:49:8

at Object.<anonymous> (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/webpack-cli/bin/cli.js:390:3)

at Module._compile (internal/modules/cjs/loader.js:688:30)

at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)

at Module.load (internal/modules/cjs/loader.js:598:32)

at tryModuleLoad (internal/modules/cjs/loader.js:537:12)

at Function.Module._load (internal/modules/cjs/loader.js:529:3)

at Module.require (internal/modules/cjs/loader.js:636:17)

at require (internal/modules/cjs/helpers.js:20:18)

at Object.<anonymous> (/Users/marklawley/Developer/jhipster-cesium-template/node_modules/webpack/bin/webpack.js:156:2)

at Module._compile (internal/modules/cjs/loader.js:688:30)

Hi Mark,

I had a more thorough investigation on your project and I noticed that you are using angular-cesium library and trying to load Cesium globally through custom webpack configuration at the same time, that is you are trying to load Cesium twice which may have unexpected effects.

I think that you first need to sort out how are you going to load Cesium. You have two options:

  1. Use the angular-cesium library in conjunction with Angular CLI
  2. Use the native Cesium library using a custom webpack configuration.

Thank you for taking a closer look. I’ve tried with and without the angular-cesium library but still run into webpack issues with Cesium. It appears that the two don’t play nicely, and I keep running into compatibility issues even after a lot of configuration and time.

With this particular project, I must use option #2. I’m grateful for the help but might have to explore other solutions, like plain Google Maps, which aren’t ideal but which I’ve gotten working already. I’ll keep the public repo up in case I can revisit and contribute to this problem in the future. Thanks again!

Hi Mark,

I have forked your project and made it working with the second option. Would you like to make a PR to your repo?

Wow, 7 minutes. You’re a hero and uber-engineer. I’d love a PR!

Haha, for god’s sake no. I fixed it some days ago, while I was experimenting with your problem.

I noticed that you were using angular-cesium and I supposed that this was obligatory for your project.