deck.gl
deck.gl copied to clipboard
SSR Error After Upgrading from 8.8 to 8.9
Description
After upgrading from 8.8 to 8.9 via npm update
, I receive the following error when trying to build my NextJS App:
Instead change the require of index.js in /Users/aemon/Worky/cerulean-ui/node_modules/@deck.gl/layers/dist/es5/text-layer/font-atlas-manager.js to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> (/Users/aemon/Worky/cerulean-ui/node_modules/@deck.gl/layers/dist/es5/text-layer/font-atlas-manager.js:17:39)
at Object.<anonymous> (/Users/aemon/Worky/cerulean-ui/node_modules/@deck.gl/layers/dist/es5/text-layer/text-layer.js:32:49)
at Object.<anonymous> (/Users/aemon/Worky/cerulean-ui/node_modules/@deck.gl/layers/dist/es5/geojson-layer/sub-layer-map.js:16:41)
at Object.<anonymous> (/Users/aemon/Worky/cerulean-ui/node_modules/@deck.gl/layers/dist/es5/geojson-layer/geojson-layer.js:32:20)
at Object.<anonymous> (/Users/aemon/Worky/cerulean-ui/node_modules/@deck.gl/layers/dist/es5/index.js:119:44)
at 9801 (/Users/aemon/Worky/cerulean-ui/.next/server/pages/index.js:1391:18)
at __webpack_require__ (/Users/aemon/Worky/cerulean-ui/.next/server/webpack-runtime.js:25:42)
at 5297 (/Users/aemon/Worky/cerulean-ui/.next/server/pages/index.js:134:79)
at __webpack_require__ (/Users/aemon/Worky/cerulean-ui/.next/server/webpack-runtime.js:25:42)
at /Users/aemon/Worky/cerulean-ui/.next/server/pages/index.js:1093:79
at __webpack_require__.a (/Users/aemon/Worky/cerulean-ui/.next/server/webpack-runtime.js:89:13)
at 5075 (/Users/aemon/Worky/cerulean-ui/.next/server/pages/index.js:1066:21)
at __webpack_require__ (/Users/aemon/Worky/cerulean-ui/.next/server/webpack-runtime.js:25:42)
at __webpack_exec__ (/Users/aemon/Worky/cerulean-ui/.next/server/pages/index.js:1499:39)
at /Users/aemon/Worky/cerulean-ui/.next/server/pages/index.js:1500:28
at Object.<anonymous> (/Users/aemon/Worky/cerulean-ui/.next/server/pages/index.js:1503:3)
at Object.requirePage (/Users/aemon/Worky/cerulean-ui/node_modules/next/dist/server/require.js:88:12)
at /Users/aemon/Worky/cerulean-ui/node_modules/next/dist/server/load-components.js:49:73
at async Object.loadComponentsImpl [as loadComponents] (/Users/aemon/Worky/cerulean-ui/node_modules/next/dist/server/load-components.js:49:26)
at async /Users/aemon/Worky/cerulean-ui/node_modules/next/dist/build/utils.js:858:32
at async Span.traceAsyncFn (/Users/aemon/Worky/cerulean-ui/node_modules/next/dist/trace/trace.js:79:20) {
code: 'ERR_REQUIRE_ESM'
Flavors
- [X] React
- [ ] Python/Jupyter notebook
- [ ] MapboxLayer
- [X] GoogleMapsOverlay
- [ ] CartoLayer
- [ ] DeckLayer/DeckRenderer for ArcGIS
Expected Behavior
After reading the Upgrade Guide, I didn't notice any breaking changes that should affect my code as it is. I should still be able to build my app.
Steps to Reproduce
I will try and supply this, but judging from the stack trace I supplied something seems to be amiss
Environment
- Framework version: 8.9
- Browser:
- OS: macOS 13.2.1
Logs
No response
+1
Tried a few tricks to see if I could get this to work on Next v13.x.x but unfortunately none of them worked:
next.config.js
transpilePackages: ['@deck.gl/layers', '@mapbox/tiny-sdf'],
experimental: {
esmExternals: 'loose',
},
In 8.9 a few upstream dependencies are updated to their latest version, including @mapbox/tiny-sdf
and d3-*
. They are pure ESM modules and cannot be imported by require()
from the commonjs entry point.
You may want to look into next.js config that lets you control the module resolution for server-side bundle - @deck.gl/*/dist/esm
is the entry point using import/export syntax. (i.e. module
instead of main
in package.json)
Whatever the solution is, we cannot go backward on these dependencies. Security vulnerabilities in those libraries are not fixed in the old versions.
Edit: I spent a little time poking around and it doesn't seem easy to override next's webpack configs. At this point I would recommend isolating your deck.gl-related imports and exclude it from SSR:
/// components/deck-map.js
import DeckGL, {TextLayer} from 'deck.gl';
export default function DeckMap() {
return <DeckGL ... />
}
/// pages/index.js
import dynamic from 'next/dynamic';
const DeckMap = dynamic(() => import('../components/deck-map'), {
ssr: false
});
export default function Home() {
return <DeckMap />;
}
deck.gl renders into a WebGLContext so it wouldn't benefit from SSR anyways.
@Pessimistress: I'm loading DeckGL (v8.9.2) and NebulaGL with a dynamic import (ssr: false), but I still get this issue when I build next build
(v13.2.4)
@DonovanCharpin The problem is not the DeckGL component. You cannot import any layer that reference the above mentioned modules (e.g. TextLayer
, GeoJsonLayer
, MVTLayer
) on the server side.
@Pessimistress my component contains a map and is loaded dynamically (not ssr)
const MyMap = dynamic(
() => import("../../components/react-map-gl/static-react-map-gl.component"),
{
ssr: false,
}
);
This component imports BitmapLayer
, GeoJsonLayer
, IconLayer
and TextLayer
from @deck.gl/layers
. At build time, it still breaks. I'm not able to build the nextjs app that I'm able to do with next13 and deck v8.8.
@DonovanCharpin Look at the trace stack of the error and it will tell you which component is doing the problematic import. Sorry I can't be of more assistance because I can only speculate based on your description.
@Pessimistress The stack was mainly the same as the one shared above. I will post my stack here as well if it can help. But basically, I don't use deckGL outside of this component and this component is not loaded on SSR, so I'm not sure what would be wrong.
I was able to confirm the fix proposed by @Pessimistress worked for us. We have a similar sounding setup @DonovanCharpin
src/pages/index.tsx --> where we do the dynamic import
src/app.tsx --> where deck.gl and layer imports live, no dynamic imports
src/layers/thing.ts --> imported in the above file
I ran into this with vitest as well due to https://github.com/vitest-dev/vitest/issues/2834. Adding alias: [{ find: /^@deck.gl\/layers$/, replacement: "@deck.gl/layers/dist/esm" }],
to vite.config resolved it.
You're awesome! This has solved my deployment issue! <3
I've tried,seems to be working. "@deck.gl/layers": "^8.9.7" "next": "^13.3.0"
None of the above works for me !
@fromwhite can you share your component and config setup?
It doesn't work for me
INDEX:
MAP:
This is quite niche but I also encountered this issue using rakkas framework. I've tried to do what's described here but nothing helped, until I moved the piece of code that was using useServerSideQuery
in the component to the separate file. So now deck.gl won't get imported on the server-side. It took me quite some time to figure out why it was having the issue in the first place, since I replaced all the imports of the component in question with the ClientSuspense
and React.lazy
.
@x17Andrew71x this weird because i tried it before and it didn't work but made a new project and worked for some reason!!
@x17Andrew71x this weird because i tried it before and it didn't work but made a new project and worked for some reason!!
That's great that you got it, my guess would be there's a version difference somewhere in the installed packages.
Hello, I have created a repo to reproduce the problem and how to fix this thanks to @Pessimistress This repo was created with latest code (by the time it was written) NextJS 13.3.0 and DeckGL 8.9.8
There are 2 pages: index and working
The index page throws the error described in this issue:
Error: require() of ES Module /project/deckgl-error/node_modules/@mapbox/tiny-sdf/index.js from /project/deckgl-error/node_modules/@deck.gl/layers/dist/es5/text-layer/font-atlas-manager.js not supported.
The page working is refactored in order to move the deckgl code to a component and dynamically import that component with ssr:false
I hope there is a better way to do this. We have a big app and the refactoring will take some time.
PS: If you want to see the map, you have to enter your mapbox token in the MAPBOX_ACCESS_TOKEN variable
Github: https://github.com/xap5xap/deckgl-error
codeSandbox: code
Hey guys,
I still have the issue with the latest version. I'm importing the map dynamically (ssr:false) and I'm using these imports in the map component:
import DeckGL from "@deck.gl/react";
import { BitmapLayer, IconLayer, TextLayer } from "@deck.gl/layers";
Could this be linked? Here is the stack I get when I run a next build
. Also, I'm using pnpm
require() of ES Module /xxx/node_modules/.pnpm/@[email protected]/node_modules/@mapbox/tiny-sdf/index.js from /xxx/node_modules/.pnpm/@[email protected][email protected][email protected]/node_modules/@deck.gl/layers/dist/es5/text-layer/font-atlas-manager.js not supported.
Instead change the require of index.js in /xxx/node_modules/.pnpm/@[email protected][email protected][email protected]/node_modules/@deck.gl/layers/dist/es5/text-layer/font-atlas-manager.js to a dynamic import() which is available in all CommonJS modules.
@DonovanCharpin Be sure you are dynamically importing everywhere in your code. Probably theres is a "component" that is importing deckgl packages without the ssr
@xap5xap I found the issue... You are right, there was a constant export.
export const META_TOOLTIP_TYPES = [...]
that was used in another part of the code and created the issue shared previously! This is a good catch because I will check all my dynamic imports now!
Seems it might still be an issue with aggregation layers.
The above fix works but as soon as I try and use the HexagonLayer
import { HexagonLayer } from '@deck.gl/aggregation-layers/typed'
It'll break
For people with a vitest issue about an ESM import, if alias failed then you can try this in your vitest.setup.tsx
file in order to mock it (this solution works only if you do not need to test rendering things):
beforeAll(() => {
vitest.mock('@deck.gl/layers/typed', () => {
return {
default: () => {},
GeoJsonLayer: class GeoJsonLayer{},
PathLayer: class PathLayer{},
TextLayer: class TextLayer{},
// ... whatever layers you are using
}
})
})
Hope it helps :)
For a NextJS setup, adding 'use client'
at the top of the file importing deck.gl
(components/deck-map.js
in this example) solved the problem for me.
See https://nextjs.org/docs/app/building-your-application/rendering/client-components
I still have the issue, and as @theonlydaleking said, there might be an issue with aggregation layers. Here is my stack with next 14.0
✓ Ready in 2.6s
○ Compiling /[spaceDomain]/book-a-room/[[...entity]] ...
⨯ ./node_modules/.pnpm/@[email protected][email protected][email protected][email protected][email protected][email protected][email protected]/node_modules/@deck.gl/layers/dist/es5/text-layer/font-atlas-manager.js:17:0
Module not found: ESM packages (@mapbox/tiny-sdf) need to be imported. Use 'import' to reference the package instead. https://nextjs.org/docs/messages/import-esm-externals
https://nextjs.org/docs/messages/module-not-found
Import trace for requested module:
./node_modules/.pnpm/@[email protected][email protected][email protected][email protected][email protected][email protected][email protected]/node_modules/@deck.gl/layers/dist/es5/text-layer/text-layer.js
./node_modules/.pnpm/@[email protected][email protected][email protected][email protected][email protected][email protected][email protected]/node_modules/@deck.gl/layers/dist/es5/index.js
./src/components/react-map-gl/static-react-map-gl.component.js
./pages/[spaceDomain]/book-a-room/[[...entity]].js
My files are all imported dynamically with dynamic, and I even tested "use client"; with no luck. I did not upgrade deck.gl to 8.9.32
, I just upgraded next.js to v14. Everything works fine with next.js 13.4.19
(I think it starts not working with 13.5.x
btw) and deck 8.9.26
.
Also, the stack above specifies deck gl 8.9.32
which is different from the version I have in local.
I tried also the other solutions above with transpile etc.
UPDATE
Nevermind, I had to install @deck.gl/layers, it was working with just deck.gl before.
I struggled with this issue for a quite a while with none of the solutions here working for me. Eventually I stumbled into this section of the docs for anyone also having issues.
// src/components/map.js
import DeckGL, {TextLayer} from 'deck.gl';
export default function Map() {
return <DeckGL ... />
}
//src/pages/app.js
import dynamic from 'next/dynamic';
const Map = dynamic(() => import('../components/map'), {ssr: false});
export default function App() {
return <Map />;
}
I ran into this with vitest as well due to vitest-dev/vitest#2834. Adding
alias: [{ find: /^@deck.gl\/layers$/, replacement: "@deck.gl/layers/dist/esm" }],
to vite.config resolved it.
this does not work for me Error: require() of ES Module /Users/alejandromorales/Documents/orix/pa-monorepo/node_modules/.pnpm/@[email protected]/node_modules/@mapbox/tiny-sdf/index.js from /Users/alejandromorales/Documents/orix/pa-monorepo/node_modules/.pnpm/@[email protected][email protected][email protected][email protected][email protected][email protected][email protected]/node_modules/@deck.gl/layers/dist/es5/text-layer/font-atlas-manager.js not supported. Instead change the require of index.js in /Users/alejandromorales/Documents/orix/pa-monorepo/node_modules/.pnpm/@[email protected][email protected][email protected][email protected][email protected][email protected][email protected]/node_modules/@deck.gl/layers/dist/es5/text-layer/font-atlas-manager.js to a dynamic import() which is available in all CommonJS modules.
is what get any ideas?