Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How-to import Cesium on Webpack #8471

Closed
serut opened this issue Dec 18, 2019 · 17 comments
Closed

How-to import Cesium on Webpack #8471

serut opened this issue Dec 18, 2019 · 17 comments

Comments

@serut
Copy link

serut commented Dec 18, 2019

I'm trying to install Cesium on Webpack, and the current tutorial looks outdated.

If I do what is inside your tutorial, i get :


import Cesium from 'cesium/Cesium'
export default class CesiumAdapter extends React.Component {
  /**
   * Lifecycle method: component did mount. Used here to load and initialize the Cesium component
   */
  componentDidMount = () => {
    var viewer = new Cesium.Viewer('cesiumContainer', {
      baseLayerPicker : false
    });
  }
  render() {
    return (
      <div
        id="cesiumContainer"
      />)
  }
}

Which makes this error :

WARNING in ./web_modules/utils/cesium-adapter/src/adapters/CesiumAdapter.jsx 37:23-29
"export 'default' (imported as 'Cesium') was not found in 'cesium/Cesium'
 @ ./web_modules/utils/cesium-adapter/src/main.js
 @ ./src/CesiumTest.jsx
 @ ./src/main.jsx

WARNING in ./web_modules/utils/cesium-adapter/src/adapters/CesiumAdapter.jsx 40:27-33
"export 'default' (imported as 'Cesium') was not found in 'cesium/Cesium'
 @ ./web_modules/utils/cesium-adapter/src/main.js
 @ ./src/CesiumTest.jsx
 @ ./src/main.jsx
ℹ 「wdm」: Compiled with warnings.

I can fix it by importing everything like that :

import * as Cesium from 'cesium/Cesium'
 [... ]
    var viewer = new Cesium.Viewer('cesiumContainer', {
      baseLayerPicker : false
    });

Or even better (may use Webpack dead code optimizer) :

import { Viewer } from 'cesium/Cesium'
 [... ]
    var viewer = new Viewer('cesiumContainer', {
      baseLayerPicker : false
    });

@mramato
Copy link
Contributor

mramato commented Dec 18, 2019

@serut I assume you're referring to https://cesium.com/docs/tutorials/cesium-and-webpack/? Yes, this definitely looks outdated (thanks for opening an issue). We recently migrated to ES6 modules and simplified a lot of things but apparently forgot to update the tutorial.

The reference example, https://github.com/AnalyticalGraphicsInc/cesium-webpack-example, was updated so you can check that out the meantime.

Honestly, using Cesium with webpack is trivial now, so I guess the question is: Is it still worth having a specific tutorial at all? @OmarShehata I'll leave that question up to you.

@serut
Copy link
Author

serut commented Dec 18, 2019

Hmm, I don't think the Cesium configuration for webpack is trivial as you need to add a little bit of specific config to webpack to get it work.
For example, I need to add :

    module: {
      unknownContextCritical: false,

Otherwise I get :

WARNING in ./node_modules/cesium/Source/Core/buildModuleUrl.js 69:31-38
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

Why don't you get that issue on your example ?

And you still need

  • CopywebpackPlugin
  • DefinePlugin CESIUM_BASE_URL

The rest of the tutorial looks outdated, things work well without them on my project.

@mramato
Copy link
Contributor

mramato commented Dec 18, 2019

Thanks @serut you're absolutely right, I shouldn't have called it trivial.

The critical dependency warning actually happens in the sample project as well, we just don't disabling the warning. (It's actually a false positive and can be safely ignored either way)

None of us are big webpack users, so this is certainly an area that can use some TLC, if anyone has any thoughts on how to improve the reference example, we are always happy to take suggestions.

The tutorial probably needs a larger overhaul.

@serut
Copy link
Author

serut commented Dec 18, 2019

What does TLC means ? https://www.urbandictionary.com/define.php?term=TLC

I think you just need to remove everything outdated and that will be good. I will make a PR if I have some spare time

@mramato
Copy link
Contributor

mramato commented Dec 18, 2019

Sorry, @serut TLC means "tender loving care": https://www.merriam-webster.com/dictionary/tender%20loving%20care

@serut
Copy link
Author

serut commented Dec 18, 2019

Allright I get it 😎

@nshen
Copy link
Contributor

nshen commented Mar 4, 2021

try vite ,it is much easier and faster
https://github.com/nshen/vite-plugin-cesium

@goldenram
Copy link

We currently have cesium working with webpack 4, and we were in the process of upgrading to webpack 5 but ran into issues with cesium. I know there are 2 PRs in the cesium-and-webpack repo waiting review. If those are merged, I assume that would fix the webpack 5 issues? Can we get an update on webpack 5 support? Thanks!

@serut
Copy link
Author

serut commented Apr 29, 2021

@goldenram I'm getting issues too with Webpack 5. No, something must be changed on Cesium, then changes on cesium-and-webpack would be mergeable.

@thw0rted
Copy link
Contributor

@serut and @goldenram , can you elaborate what your issues are? Is it related to asset import?

When you say there are PRs waiting, I assume you're talking about CesiumGS/cesium-webpack-example#25 and CesiumGS/cesium-webpack-example#23. Both of those work a little differently from my current config. One copies Cesium assets (e.g. CSS and worker scripts) into ./dist using the copy plugin, then imports them using a ../dist/... relative path, which seems wrong to me -- your src depends on dist? The other imports CSS using ../node_modules/cesium/Build/... which at least works but could still be confusing when mixed with absolute specifiers (import { ... } from "cesium").

What I did was to set resolve.exportsFields to []. This prevents Webpack from using exports in package.json, which is necessary to access assets with e.g. import "cesium/Source/Widgets/widgets.css", until #9212 is resolved. There's a lot of discussion there but the short version is that the exports field that ships with Cesium will not work with Webpack 5.

@serut
Copy link
Author

serut commented Apr 29, 2021

@thw0rted I have the following webpack configuration :
https://resium.darwineducation.com/installation2

I had some unstable test issues so I upgraded my stack with Webpack 5 and a new test runner :
https://github.com/serut/regards-frontend-webpack-5

I end up with the following error when building :

ERROR in ./web_modules/utils/cesium-adapter/src/CesiumProvider.jsx 27:2-39
Module not found: Error: Package path ./Widgets/widgets.css is not exported from package /app_to_build/node_modules/cesium (see exports field in /app_to_build/node_modules/cesium/package.json)
 @ ./web_modules/utils/cesium-adapter/src/main.js 1:0-61 1:0-61
 @ ./web_modules/modules/search-results/src/components/user/tabs/results/map/MapComponent.jsx 30:0-60 121:50-64
 @ ./web_modules/modules/search-results/src/containers/user/tabs/results/map/MapContainer.jsx 37:0-88 415:40-52
 @ ./web_modules/modules/search-results/src/components/user/tabs/results/map/MapViewComponent.jsx 36:0-88 185:42-54
 @ ./web_modules/modules/search-results/src/containers/user/tabs/results/map/MapViewContainer.jsx 26:0-96 141:44-60
 @ ./web_modules/modules/search-results/src/components/user/tabs/results/SearchResultsComponent.jsx 32:0-93 133:50-66
 @ ./web_modules/modules/search-results/src/containers/user/tabs/results/SearchResultsContainer.jsx 38:0-101 208:40-62
 @ ./web_modules/modules/search-results/src/components/user/tabs/TabsContentComponent.jsx 28:0-98 63:46-68 85:46-68
 @ ./web_modules/modules/search-results/src/containers/user/tabs/TabsContentContainer.jsx 32:0-86 92:44-64
 @ ./web_modules/modules/search-results/src/components/user/ModuleComponent.jsx 34:0-83 64:53-73
 @ ./web_modules/modules/search-results/src/containers/ModuleContainer.jsx 30:0-65 75:42-57

@thw0rted
Copy link
Contributor

thw0rted commented Apr 29, 2021

OK, that's exactly why I said to set resolve.exportsFields: []. I understand that the details in #9212 are pretty involved, it's a lot to read.

The slightly less short explanation is that Webpack 5 tries to use the exports field in package.json, which webpack 4 did not do. This means that if an asset is not exported by exports, Webpack will refuse to import it, period. Here is the value of that field today:

  "exports": {
    "./package.json": "./package.json",
    ".": {
      "require": "./index.cjs",
      "import": "./Source/Cesium.js"
    }
  },

If you don't disable the default exportsFields, the only thing you can import from Cesium is package.json, or the ESM top level source code (Source/Cesium.js, via bare import like import { Viewer } from "cesium"). This is obviously wrong -- at a minium, library consumers must import stylesheets and web worker scripts, if not other assets like images, approximate-terrain-height data, etc -- which is why I asked for #9212 to be re-opened. In the meantime you just have to tell Webpack to ignore it, which will make it fall back to legacy Node-style resolution for bare import specifiers.

Before I forget, there's actually a second related problem. You may also have to add

        rules: [{
            test: /\.js$/,
            resolve: {
                fullySpecified: false,
            },
        }, ...

because sometimes type: module deps can fail to use full filenames (including a .js extension!) in import specifiers. This setting falls back to legacy behavior, i.e., Node-style import resolution.

@TJKoury
Copy link
Contributor

TJKoury commented Apr 29, 2021

...or you can just forget all that mess and use c137.js!

@serut
Copy link
Author

serut commented Apr 29, 2021

I don't know the right value for the package.json, but definitly Cesium is not buildable with Webpack 5 as it does not follow new standards. I'm trying to keep the type of build I have (it looks like it removes dead code on prod, fast build on dev...).

My build is working on Jenkins now I've added :

sed -i "s+\".\": {+\"./\": \"./Source/\",\".\": {+g" /app_to_build/node_modules/cesium/package.json

It changes the content from :

  # BEFORE node_modules/cesium/package.json
  "exports": {
    "./package.json": "./package.json",
    ".": {
      "require": "./index.cjs",
      "import": "./Source/Cesium.js"
    }
  },


  # AFTER node_modules/cesium/package.json
  "exports": {
    "./package.json": "./package.json",
    "./": "./Source/",
    ".": {
      "require": "./index.cjs",
      "import": "./Source/Cesium.js"
    }
  },

I also removed resolved.alias as it looks superflous from my conf.
And everything works as expected ! Dev, tests and prod builds

@thw0rted I did not changed exportsFields neither provides fullySpecified: false
@TJKoury I would loose more time to explain to my customer why the dependency changed and now we use a fork with private source code than fixing every repo on github !

@TJKoury
Copy link
Contributor

TJKoury commented Apr 29, 2021

@serut Well it’s available for free whenever you want it. Maybe Cesium will partner with us soon so we can open up the build process.

@thw0rted
Copy link
Contributor

That makes sense. Your fix is another good solution, though in my case it's a bit of a pain to modify the installed library like that. I'm hoping that Cesium is willing to re-open the issue and take a PR fixing package.json for everybody.

@ggetz
Copy link
Contributor

ggetz commented Sep 19, 2022

Hi all, we've recently made some updates to CesiumJS's package.json to allow better usage in webpack and other bundlers. We've updated cesium-webpack-example to reflect the changes. Also, we've opened an issue for potentially inlining static assets in builds if anyone is interested in going down that route instead.

I think those all address each of the concerns in this issue, so I'll close it. Thanks!

@ggetz ggetz closed this as completed Sep 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants