When running in a version of Node that supports ES6, this will now load
the ES6 version of Cesium instead of the transpiled modules or modules
loaded via ESM. It does it by setting the module type and entry points in
package.json.
There are 3 use cases this allows:
1. Roll-up and other tools that support resolving front-end dependencies
via node_modules can now make use of Cesium.
`import { defined, JulianDate } from 'cesium';` can now be used in such
systems instead of specifying the relative path to Source/Cesium.js This
makes it easier to write reusable components that rely on Cesium.
2. Since we are using Cesium ES6, node bundlers can perform treeshaking
and eliminate unused code, basically allow for building combined minified
node code with tools like roll-up.
3. Requiring in individual modules, such as `cesium/Source/Core/Cartesian3.js`
is now possible in situations where pulling the primary entry point is
not desired.
The one downside of this change is that ES6 versions of Node will no
longer automatically pull in the combined/minimized version of Cesium.js,
though its still technically possible to do via manual esm usage. This
may (or may not) impact performance under node in certain situations but
ultimately a build process is properly the preferred method for optimizing
node applications.
See https://github.com/AnalyticalGraphicsInc/cesium/pull/8224 for details.
eslint
There are a handful of new .eslintrc.json files, mostly to identify the files that are still AMD modules (Sandcastle/Workers). These are needed because you can't change the parser type with a comment directive (since the parser is the thing reading the file). We can finally detect unusued modules! So those have all been cleaned up as well.
requirejs -> rollup & clean-css
requirejs, almond, and karma-requirejs have all been removed. We now use rollup for building and minifying (via uglify) JS code and clean-css for css. These changes are fairly straight-forward and just involve calling rollup instead of requirejs in the build process.
Overall build time is significantly faster. CI is ~11 minutes compared to ~17 in master. Running makeZipFile on my machine takes 69 seconds compared to 112 seconds in master. There's probably plenty of room for additional optimization here too.
We wrote an published a small npm module, rollup-plugin-strip-pragma, for stripping the requirejs pragmas we use out of the release builds. This is maintained in the Tools/rollup-plugin-strip-pragma directory.
As for what we produce. The built version of Cesium is now a UMD module. So it should work anywhere that hasn't made the jump to ES6 yet. For users that were already using the "legacy" combined/minified approach, nothing changes.
One awesome thing about roll-up is that it compiles all of the workers at once and automatically detects shared codes and generates separate bundles under the hood. This means the size of our worker modules shrink dramatically and Cesium itself will load them much faster. The total minified/gzipped size of all workers in master is 2.6 MB compared to 225 KB in this branch! This should be most noticeable on demos like Geometry & Appearances which load lots of workers for the various geometry typs.
roll-up is also used to build Cesium Viewer, which is now an ES6 app.
We use clean-css via gulp and it is also a straightforward change from requirejs that requires no special mention.
Workers
While the spec allows for ES6 Web Workers, no browser actually supports them yet. That means we needed a way to get our workers into non-ES6 form. Thankfully, roll-up can generate AMD modules, which means we now have a build step to compile our Worker source code back into AMD and use the existing TaskProcessor to load and execute them. This build step is part of the standard build task and is called createWorkers. During development, these "built" workers are un-optimized so you can still debug them and read the code.
Since there is a build step, that means if you are changing code that affects a worker, you need to re-run build, or you can use the build-watch task to do it automatically.
The ES6 versions of Worker code has moved into Source/WorkersES6 and we build the workers into their "old home" of Source/Workers. cesiumWorkerBootstrapper and transferTypedArrayTest which were already non-AMD ES5 scripts remain living in the Workers directory.
Surprisingly little was changed about TaskProcessor or the worker system in general, especially considering that I thought this would be one of the major hurdles.
ThirdParty
A lot of our ThirdParty either already had a hand-written wrapper for AMD (which I updated to ES6) or had UMD which created problems when importing the same code in both Node and the browser. I basically had to update the wrapper of every third-party library to fix these problems. In some cases I updated the library version itself (Autolinker, topojson). Nothing to be too concerned about, but future clean-up would be using npm versions of these libraries and auto-generating the wrappers as needed so we don't hand-edit things.
Sandcastle
Sandcastle is eternal and manages to live another day in it's ancient requirejs/dojo 1.x form. Sandcastle now automatically uses the ES6 version of Cesium if it is available and fallsback to the ES5 unminified version if it is now. The built version of Sandcastle always uses CesiumUnminified, just like master. This means Sandcastle still works in IE11 if you run the combine step first (or use the relase zip)
Removed Cesium usage from Sandcastle proper, since it wasn't really needed
Generate a VERSION propertyin the gallery index since Cesium is no longer being included.
Remove requirejs from Sandcastle bucket
Update bucket to use the built version of Cesium if it is available by fallbackto the ES6 version during development.
Standalone.html was also updated
There's a bit of room for further clean-up here, but I think this gets us into master. I did not rename bucket-requirejs.html because I'm pretty sure it would break previously shared demos. We can put in some backwards compatible code later on if we want. (But I'd rather just see a full Sandcastle rewrite).
Specs
Specs are now all ES6, except for TestWorkers, which remain standard JS worker modules. This means you can no longer run the unbuilt unit tests in IE11. No changes for Chrome and Firefox.
Since the specs use ES6 modules and built Cesium is an ES5 UMD, I added a build-specs build step which generates a combined ES5 version of the specs which rely on Cesium as a global variable. We then inject these files into jasmine instead of the standard specs and everything works exactly as it did before. SpecRunner.html has been updated to inject the correct version of the script depending on the build/release query parameters.
The Specs must always use Cesium by importing Source/Cesium.js, this is so we can replace it with the built Cesium as describe above.
There's a bunch of room for clean-up here, such as unifying our two copies of jasmine into a single helper file, but I didn't want to start doing that clean-up as part of this already overly big PR. The important thing is that we can still test the built version and still test on IE/Edge as needed.
I also found and fixed two bugs that were causing failing unit tests, one in BingMapsImageryProviderSpec.js (which was overwriting createImage andnot setting it back) and ShadowVolumeAppearance.js (which had a module level caching bug). I think these may have been the cause of random CI failures in master as well, but only time will tell.
For coverage, we had to switch to karma-coverage-istanbul-instrumenter for native ES6 support, but that's it.
Finally, I updated appveryor to build Cesium and run the built tests under IE. We still don't fail the build for IE, but we should probably fix that if we want to keep it going.
NodeJS
When NODE_ENV is production, we now require in the minified CesiumJS directly, which works great because it's now a UMD module. Otherwise, we use the excellant esmpackage to load individual modules, it was a fairly straightforward swap from our old requirejs usage. We could probably drop esm too if we don't care about debugging or if we provie source maps at some point.
1. Replace our ancient, windows-only jscoverage implementation with
karma-coverage, which works on all platforms and does not require a
separate instrumentation step. You now run coverage by simply typing
`npm run coverage`. This also provides improved results, such as branch
coverage, which the old system did not.
2. Updated Testing Guide
3. Remove old instrument link from index.html
4. Remove jscoverage and related code.
1. We weren't handling already-compressed gzips when setting Content-type
2. Our `getMimeType` helper function was incorrect and also skipped a ton
of files that should be compressed.
3. Remove dependency on unneeded `compressible` module.
4. Aggressively compress everything except images/video.
5. Warn if we add an already gzipped file or a new extention type that
we don't account for in getMimeType.
Supercedes #5651 which I tried to originally update but ran into some
merge conflicts that just made it easier to re-do.
I did the simplest possible port for now since I didn't want to cram a
whole bunch of clean-up into this PR.
Also updated `event-stream` and `karma` since they required no code changes
on our end.
`google-earth-dbroot-parser.js` is a huge dependency (487 KB source, 202KB
minified). It's also only needed if you are using a Google Earth server.
In order to avoid bloat and paying the penalty every time Cesium is loaded,
this change loads it on demand the first time it's needed.
I didn't use jsonp for this because there's no server to parse the query
and wrap the code in a callback. Instead we just load the script directly
into a unlikely to collide global variable.
The file gets minified and copied to ThirdParty, similar to what we were
already doing with the wasm file.
Also fixed a bug in buildCesiumViewer where it wasn't copying all the
necessary files to its own build output.
Also extracted `loadAndExecuteScript` out of Resource.js, but had to keep
a version of it in Resource.js because cleaning up test abuse of it is
a much larger change best for another PR. (I'll write up an issue).
Since Chrome added an officially supported headless mode, there's no
reason to use Electron for our unit tests. This will be both more accurate
(uses actual Chrome) and also gets rid of the rather large Electron
dependency.
WebGL is disabled in headless, so we only use headless on CI (because we
also disable webGL tests there). When running locally, it just shows an
actual Chrome window. Chrome has an issue and plans to address this:
https://bugs.chromium.org/p/chromium/issues/detail?id=765284
1. Update to eslint 5.2.0, which has some new default rules.
2. Disable `no-self-assign` in Cesium tests, this new rule is useful but
not in our specs.
3. Allow ES 2017 in node code, this includes async/await, which we have
started using in Cesium-related Node projects
4. Add `no-var` and `prefer-const` as rules for Node code, we've already
have been using them with success in other projects.
5. Bump eslint-config-cesium to 6.0.0 and update CHANGES so I can release
once this is merged.
1. nodir now defaults to true in `globby`.
2. We had to disable random test ordering in jasmine since Cesium's unit
tests unfortunately do not work when ran in a random order.
1. Caching makes eslint only take ~3 seconds plus any files that have
changed since the last time you ran it. Since it's unlikely devs are
touching every tile between runs, this makes eslint much incredibly faster
in the average case. Also added the genereated `.eslintcache` to git
ignore.
2. Switched to the pure cli version of eslint and remove `eslint-watch`,
which I'm pretty sure no one uses anyway. This simplified our usage and
means we lint all js and html files by default except for the globs
specifically listed in `.eslintignore` This also shaves 2-4 seconds off
startup time because we're not loading gulpfile.js anymore.
3. Fixed an issue in `index.release.html`, which was previously not linted.
We were stuck on an old version of `strip-comments` that just happened
to work on glsl via regex. This new module actually uses a tokenizer
and seems to be more well maintained.