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 can I include mapbox-gl in Gatsby? #6667

Closed
lipis opened this issue Jul 23, 2018 · 16 comments
Closed

How can I include mapbox-gl in Gatsby? #6667

lipis opened this issue Jul 23, 2018 · 16 comments
Labels
type: question or discussion Issue discussing or asking a question about Gatsby

Comments

@lipis
Copy link
Contributor

lipis commented Jul 23, 2018

I'm trying to include the https://github.com/mapbox/mapbox-gl-js in a Gatsby project, but I'm getting an error during build. Works nicely in dev mode.

(If someone wants to try this should be easier: https://github.com/alex3165/react-mapbox-gl)

...{}),!this.workerSources[e][t][r]){var i={send:function(t,r,i){n.actor.send(t,r,i,e);}};this.workerSources[e][t][r]=new this.workerSourceTypes[t](i,this.getLayerIndex(e));}return this.workerSources[e][t][r]},He.prototype.getDEMWorkerSource=function(e,t){return this.demWorkerSources[e]||(this.demWorkerSources[e]={}),this.demWorkerSources[e][t]||(this.demWorkerSources[e][t]=new D),this.demWorkerSources[e][t]},"undefined"!=typeof WorkerGlobalScope&&"undefined"!=typeof self&&self instanceof WorkerGlobalScope&&new He(self),He});
  32 |


  WebpackError: ReferenceError: self is not defined

  - mapbox-gl.js:29
    [lib]/[mapbox-gl]/dist/mapbox-gl.js:29:206

  - mapbox-gl.js:22 define
    [lib]/[mapbox-gl]/dist/mapbox-gl.js:22:1

  - mapbox-gl.js:33
    [lib]/[mapbox-gl]/dist/mapbox-gl.js:33:1

  - mapbox-gl.js:3
    [lib]/[mapbox-gl]/dist/mapbox-gl.js:3:1

  - mapbox-gl.js:6 Object../node_modules/mapbox-gl/dist/mapbox-gl.js
    [lib]/[mapbox-gl]/dist/mapbox-gl.js:6:2

  - bootstrap:19 __webpack_require__
    lib/webpack/bootstrap:19:1

  - map.js:21 Object../node_modules/react-mapbox-gl/lib/map.js
    [lib]/[react-mapbox-gl]/lib/map.js:21:1

  - bootstrap:19 __webpack_require__
    lib/webpack/bootstrap:19:1

  - index.js:3 Object../node_modules/react-mapbox-gl/lib/index.js
    [lib]/[react-mapbox-gl]/lib/index.js:3:1

  - bootstrap:19 __webpack_require__
    lib/webpack/bootstrap:19:1


  - bootstrap:19 __webpack_require__
    lib/webpack/bootstrap:19:1

  - sync-requires.js:8 Object../.cache/sync-requires.js
    lib/.cache/sync-requires.js:8:51

  - bootstrap:19 __webpack_require__
    lib/webpack/bootstrap:19:1

  - static-entry.js:9 Module../.cache/static-entry.js
    lib/.cache/static-entry.js:9:22

  - bootstrap:19 __webpack_require__
    lib/webpack/bootstrap:19:1


error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
@ascorbic
Copy link
Contributor

I'm not sure about Mapbox, but with Leaflet the problem is that it expects to find window, which isn't available in production build. The fact it works in develop means it may be a similar problem. I had to use a silly workaround to load the library only on componentDidMount: https://github.com/aerian-studios/aerian-site-rebuild/blob/master/src/components/MapView/MapView.tsx

@m-allanson
Copy link
Contributor

As @ascorbic mentions, this is typically caused by libraries that expect to always run in a browser environment. During gatsby build, Gatsby runs your code in a Node.js environment to render out all your static html files, so browser globals like window don't exist.

Maybe that's not exactly what's happening here (I don't think self is a browser global?), but it'd be a good first step to investigate. There's a bit of info here https://www.gatsbyjs.org/docs/debugging-html-builds/

Also searching the mapbox-gl-js repo for ReferenceError: self is not defined provides a few results that might be relevant.

@m-allanson m-allanson added the type: question or discussion Issue discussing or asking a question about Gatsby label Jul 24, 2018
@lipis
Copy link
Contributor Author

lipis commented Jul 24, 2018

Would that work in Gatsby? mapbox/mapbox-gl-js#4593 (comment)

(can't test it at the moment)

@lipis
Copy link
Contributor Author

lipis commented Aug 1, 2018

Here is the minimal example that works locally, but fails during build: https://github.com/lipis/mapbox-gatsby

I didn't manage to make it work.. can anyone else take a look?

(Feel free to use the access key, it's for testing purposes only and I'll delete it afterwards)

@lipis
Copy link
Contributor Author

lipis commented Aug 2, 2018

Thanks to @herrmannplatz!!

In gatsby-node.js:

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

@lipis lipis closed this as completed Aug 2, 2018
@stemmlerjs
Copy link

I wasn't able to get mine to work as per the above suggestions. I ended up mocking my implementation to get it to work.

let mapboxgl
let ReactMapboxGl = {}

if (typeof window !== `undefined`) {
  mapboxgl = require('mapbox-gl')
  ReactMapboxGl = require('react-mapbox-gl')
} else {
  ReactMapboxGl.Map = () => {
    return class Mock extends React.Component {
      constructor() {
        super()
      }
      render() {
        return <div />
      }
    }
  }
}

const Map = ReactMapboxGl.Map({
  accessToken:  '[your-token-here]',
})

class DirectoryMap extends React.Component {
  constructor(props) {
    super(props)
  }

  render() {
    return (
      <div className="directory-map">
        <Map
          ref={e => {
            this.map = e
          }}
          zoom={[11]}
          speed={[0.6]}
        >
        </Map>
      </div>
    )
  }
}

@jonlow
Copy link
Contributor

jonlow commented Jan 31, 2019

For this to work in the latest version of Gatsby, you need to modify #6667 (comment) to this:

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

so loaders.null() instead of null-loader, as per https://www.gatsbyjs.org/docs/debugging-html-builds/#fixing-third-party-modules

@arhoy
Copy link

arhoy commented Nov 5, 2019

@jonlow I tried this but it is not working for me, I am not really sure what is going on in the code above you explain or take a look at my repo here to see why I cannot load mapbox in production?

Thanks for any help in advance
https://github.com/arhoy/fashion-two

@jonniebigodes
Copy link

@arhoy if you don't mind i'll take a look tomorrow and see if i can provide you with a solution to the issue. Do you mind waiting a bit?

@arhoy
Copy link

arhoy commented Nov 5, 2019 via email

@chriswhong
Copy link
Contributor

For those trying to modify onCreateWebpackConfig in gatsby-node.js, here's an example of modifying existing settings to add special handling for mapboxGL: https://github.com/brendan-ward/gatsby-starter-mapbox/blob/master/gatsby-node.js

huy-nguyen added a commit to covid19-hg/covid19hg that referenced this issue Mar 25, 2020
huy-nguyen added a commit to covid19-hg/covid19hg that referenced this issue Apr 8, 2020
@jahlherapath
Copy link
Contributor

Have tried all the above solutions and am still having troubles with my build. Any help would be much appreciated!

@woss
Copy link

woss commented May 7, 2021

none of the above worked for me so I did the inline exclusion like this

import mapboxgl from "!mapbox-gl" // https://webpack.js.org/concepts/loaders/#inline

Following the MApbpx guideline https://docs.mapbox.com/mapbox-gl-js/api/#excluding-gl-js-explicitly-from-transpilation

@Hless
Copy link

Hless commented Feb 3, 2022

None of the above worked, because I was using a React library that included mapbpx-gl under the hood. By checking the mapbox docs I found another solution that worked.

You can add the following the following property to package.json:
"browserslist": ["defaults", "not ie 11"]

This is the default browserlist config (> 0.5%, last 2 versions, Firefox ESR, not dead), while additionally removing IE11 support, which I find acceptable at this point.

I did try to find a solution by trying to change the babel transpilation excludes, but I found this to be too difficult with gatsby.

@traversal
Copy link

@Hless, if you were using react-map-gl as I was, or for anyone else who is using that, here is a way to get this going in a Gatsby build (well it worked for me):

First, I installed worker-loader:

npm i --save-dev worker-loader

Then in gatsby-node.js I added this (among other rules):

actions.setWebpackConfig({
  module: {
    rules: [
      {
        test: /\bmapbox-gl-csp-worker.js\b/i,
        use: { loader: 'worker-loader' },
      },
    ]
  },
});

if (stage === 'build-html') {
  actions.setWebpackConfig({
    module: {
      rules: [
        {
          test: /mapbox-gl/,
          use: loaders.null(),
        },
      ]
    }
  })
}

All of the above is documented in various places, but the secret-sauce comes from the Map component in react-map-gl allowing you to override the library used for mapbox-gl. Here we're still really using mapbox-gl, but we need to modify the workerClass as described in https://docs.mapbox.com/mapbox-gl-js/guides/install/#transpiling

I created a wrapper component for this in Typescript like so (excuse the @ts-ignores, I couldn't work out how to make Typescript ignore the lack of types for those libs):

/* A wrapper around react-map-gl's Map component to load the correct CSS, and tweak the workerClass to allow this to work with Gatsby */
import React from 'react';
// @ts-ignore
import mapboxgl from 'mapbox-gl/dist/mapbox-gl';
// @ts-ignore
import MapboxWorker from 'mapbox-gl/dist/mapbox-gl-csp-worker';
// @ts-ignore
mapboxgl.workerClass = MapboxWorker;
import { Map as MapGL, MapProps } from 'react-map-gl';
import 'mapbox-gl/dist/mapbox-gl.css';

export const Map: React.FC<MapProps> = (props) => 
  <MapGL {...props} mapLib={mapboxgl} />

Now I just use the Map component from above, and I no longer get the transpiling web worker errors in a Gatsby production build.

Quite a nightmare, but thought this might help someone else avoid wasting hours on it! :)

@edsonJordan
Copy link

Do you have a repository where I can see the project?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: question or discussion Issue discussing or asking a question about Gatsby
Projects
None yet
Development

No branches or pull requests