Search code examples
mapboxgatsbynetlifymapbox-gl

gatsby build fails when adding mapbox-gl-geocoder to gatsby.js


I have a gatsby.js application with mapbox-gl and it all worked successfully until I tried to include the mapbox-gl-geocoder package to add search functionality.

I have installed it using npm as the following:

npm install mapbox/mapbox-gl-geocoder --save

then, added it to the React component:

import '@mapbox/mapbox-gl-geocoder/lib/mapbox-gl-geocoder.css';
import MapboxGeocoder from '@mapbox/mapbox-gl-geocoder';

and inside a useEffect hook:

  map.addControl(
      new MapboxGeocoder({
        accessToken: mapboxgl.accessToken,
        zoom: 20,
        placeholder: 'Enter City',
        mapboxgl: mapboxgl
      }), 'top-left'
    );

locally, when I run gatsby develop it works as it should, but when I deploy it with Netlify, I get the following error:

:24:21 PM: error Generating SSR bundle failed
1:24:21 PM: Can't resolve 'electron' in '/opt/build/repo/node_modules/@mapbox/mapbox-sdk/node_modules/got'
1:24:21 PM: If you're trying to use a package make sure that 'electron' is installed. If you're trying to use a local file make sure that the path is correct.

it seems that mapbox-gl-geocoder has a dependency to @mapbox/mapbox-sdk and the mapbox-sdk has a dependency to got that somehow needs electron ?

The only thing i can read about electron in the got npm page is the following:

Electron support has been removed
The Electron net module is not consistent with the Node.js http module. See #899 for more info.

In any way, I tried to install electron with npm to see if the errors are gone, and the build started to fail with new error indicating that the window object is not available.

10:35:45 AM: error "window" is not available during server side rendering.

Googling that error led me to some answers about not loading the packages in gatsby-node.js but that didn't help either.


Solution

  • When dealing with third-party modules that use window in Gatsby you need to add a null loader to its own webpack configuration to avoid the transpilation during the SSR (Server-Side Rendering). This is because gatsby develop occurs in the browser while gatsby build occurs in the Node server where obviously there isn't a window or other global objects.

    exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
      if (stage === "build-html") {
        actions.setWebpackConfig({
          module: {
            rules: [
              {
                test: /@mapbox/,
                use: loaders.null(),
              },
            ],
          },
        })
      }
    }
    

    Keep in mind that the test value is a regular expression that will match a folder under node_modules so, ensure that the /@mapbox/ is the right name.

    Using a patch-package may work but keep in mind that you are adding another package, another bundled files which may have a performance effect. The proposed snippet is a built-in solution that happens when you build your application.