deck.gl: 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

  • React
  • Python/Jupyter notebook
  • MapboxLayer
  • 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

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 17
  • Comments: 33

Commits related to this issue

Most upvoted comments

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.

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',
},

None of the above works for me !

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 😃

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

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

INDEX: image

MAP: image

A possible solution here would be to configure our build step to bundle @mapbox/tiny-sdf and any other ESM-only packages, moving them from dependencies to devDependencies inlined into the published bundle.

The main obstacle is that the esbuild API does not offer a good way to specify, “externalize everything except X”. Without that we’d have to explicitly list every dependency that isn’t X. I’ve upvoted the relevant feature requests on esbuild…

… and offered to contribute a CommonJS build to @mapbox/tiny-sdf:

Either of those should unblock deckgl.

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 />;
}

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

@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.

@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)