React-map-gl: Unable to use react-map-gl in create-react-app

Created on 10 Jan 2017  ·  21Comments  ·  Source: visgl/react-map-gl

Did someone manage to make it work in create-react-app ?

I got this error:

index.js:9Uncaught TypeError: Cannot convert undefined or null to object
    at Function.keys (<anonymous>)
    at new module.exports (index.js:9)
    at Object.<anonymous> (web_worker.js:5)
    at __webpack_require__ (bootstrap 6c4040e…:555)
    at fn (bootstrap 6c4040e…:86)
    at Object.<anonymous> (worker_pool.js:4)
    at __webpack_require__ (bootstrap 6c4040e…:555)
    at fn (bootstrap 6c4040e…:86)
    at Object.<anonymous> (global_worker_pool.js:2)
    at __webpack_require__ (bootstrap 6c4040e…:555)

My component is quite simple

import React from 'react';
import MapGL from 'react-map-gl';
#
const MAPBOX_TOKEN = 'xxxx';

export function Map() {
  return (
    <div>
      <MapGL
        width={400}
        height={400}
        latitude={37.7577}
        longitude={-122.4376}
        zoom={8}
        mapboxApiAccessToken={MAPBOX_TOKEN}
        onChangeViewport={ (viewport) => {
          const { latitude, longitude, zoom } = viewport;
          // Optionally call `setState` and use the state to update the map.
        }}
      />
    </div>
  );
}

Thank you in advance for taking interest in this issue.

Most helpful comment

Yes indeed and I was wondering if there was a way to import react-map-gl without editing webpack config since create-react-app does the webpack dirty work for you but it seems that there aren't any other way than running npm run eject and follow deck.gl webpack example.

I think the issue comes from the fact that mapbox-gl is not directly compatible with webpack. I managed to make your code work in create-react-app without ejecting by doing a small hack described here:
```
import mapboxgl from 'mapbox-gl/dist/mapbox-gl'
````
but I don't think it is a good solution...

Anyway, thank you for your quick reply!

All 21 comments

Looks like a webpack config issue. Take a look at the instructions in our README

Yes indeed and I was wondering if there was a way to import react-map-gl without editing webpack config since create-react-app does the webpack dirty work for you but it seems that there aren't any other way than running npm run eject and follow deck.gl webpack example.

I think the issue comes from the fact that mapbox-gl is not directly compatible with webpack. I managed to make your code work in create-react-app without ejecting by doing a small hack described here:
```
import mapboxgl from 'mapbox-gl/dist/mapbox-gl'
````
but I don't think it is a good solution...

Anyway, thank you for your quick reply!

@gauthierrodaro which files did you patch?

@fb-owen-vandijk, Here is a zip of the patch I did.

As you can see it was patched from an older version of the repo. It was only intended for testing purposes and I would not recommend this.

map-gl.zip

@gauthierrodaro thanks! very helpful.

In the end I decided to go with https://github.com/alex3165/react-mapbox-gl which I believe has the same workaround implemented.

From other issue

The issue about create-app can't be done without adding what's necessary in the webpack configuration and that have been documented. The error is coming from our mapbox dependency anyway, so there isn't much we can do at this level.
@Apercu

I created empty project with create-react-app. When I do

import MapGL from 'react-map-gl'

I see in browser console Uncaught SyntaxError: Unexpected token import. But when I do:

import mapboxgl from 'mapbox-gl';

I see warning Critical dependencies: 1:481-488 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results. @ ./~/mapbox-gl/dist/mapbox-gl.js 1:481-488, but no errors

Related: https://github.com/mapbox/mapbox-gl-js/issues/1649

Realised that current master is 3.0.0.alpha5. While npm version is 1.8... something. Hate when this happens.

Installed github versions with:

yarn add https://github.com/uber/react-map-gl.git
cd node_modules/react-map-gl
yarn
npm run build-es5
npm run build-es6

Now if I do import MapGL from 'react-map-gl/dist/index.js' I get Uncaught SyntaxError: Identifier 'Buffer' has already been declared

If I do import MapGL from 'react-map-gl/dist-es6/index.js' I get Uncaught SyntaxError: Unexpected token export.

@stereobooster

Realised that current master is 3.0.0.alpha5. While npm version is 1.8... something. Hate when this happens.

Per npm info latest official version is 2.0.2. There was however a patch to v1 (1.8.2) published after that. Sounds like you did a yarn or npm install and it picked the 1.8.2 (because it was the latest release non-beta-tagged release, even though it doesn't have the highest version number?).

Apologies for this, not quite sure why this happens (but not totally surprised, have seen similar surprises from npm and yarn in the past). Maybe the easiest thing is just to publish a dummy 2.0.3 (@abmai).

     $ npm info react-map-gl
     ...
     '1.8.0': '2017-01-14T00:01:03.780Z',
     '2.0.0': '2017-01-17T21:56:53.658Z',
     '1.8.1': '2017-01-24T18:24:20.770Z',
     '2.0.1': '2017-01-24T19:59:16.514Z',
     '2.0.2': '2017-02-10T02:00:00.595Z',
     '3.0.0-alpha.1': '2017-03-10T00:53:59.320Z',
     '1.8.2': '2017-03-15T21:40:42.492Z',
     '3.0.0-alpha.2': '2017-03-23T20:15:08.730Z',
     '3.0.0-alpha.3': '2017-03-27T23:01:30.344Z',
     '3.0.0-alpha.4': '2017-03-27T23:38:17.188Z',
     '3.0.0-alpha.5': '2017-03-29T23:56:32.428Z' },

@stereobooster

Now if I do import MapGL from 'react-map-gl/dist/index.js' I get Uncaught SyntaxError: Identifier 'Buffer' has already been declared

This sounds strange, never saw this. does this happen if react-map-gl is the only thing you include? Can you inspect your generated bundle and search for Buffer and see if you can find anything?

If I do import MapGL from 'react-map-gl/dist-es6/index.js' I get Uncaught SyntaxError: Unexpected token export.

That's expected. In react-map-gl v3, the dist-es6 folder has been added to support "tree-shaking" (removal of unused code from the final bundle). It should only be used by tree shaking bundlers, e.g. webpack2 and rollup. There are separate entry points specified in package.json to support autodetection of dist folder, you should not need to import a specific dist folder like this.

This sounds strange, never saw this. does this happen if react-map-gl is the only thing you include? Can you inspect your generated bundle and search for Buffer and see if you can find anything?

Yes react-map-gl is the only thing that I include. Here is example code https://github.com/stereobooster/create-react-app-map-gl (change import MapGL from 'react-map-gl/dist-es6/index.js' to dist/index.js)

It should only be used by tree shaking bundlers, e.g. webpack2 and rollup

I switched to webpack 2. Here is example code https://github.com/stereobooster/create-react-app-map-gl/tree/webpack-2

Now I get:

Uncaught TypeError: Cannot convert undefined or null to object
    at Function.keys (<anonymous>)
    at new module.exports (index.js:9) // node_modules/react-map-gl/node_modules/webworkify/index.js

Which is:

var bundleFn = arguments[3];
var sources = arguments[4];
var cache = arguments[5];

var stringify = JSON.stringify;

module.exports = function (fn, options) {
    var wkey;
    var cacheKeys = Object.keys(cache);

For webpack 2 and react-map-gl 2: https://github.com/stereobooster/create-react-app-map-gl/tree/react-map-gl-2

Uncaught Error: Module parse failed: node_modules/react-map-gl/node_modules/mapbox-gl/js/util/util.js Unexpected token (15:35)
You may need an appropriate loader to handle this file type.
|  * @private
|  */
| exports.easeCubicInOut = function(t: number): number {
|     if (t <= 0) return 0;
|     if (t >= 1) return 1;

And this is bug from Mapbox GL JS, which does not provide ES6 modules with flow-types stripped. Created ticket https://github.com/mapbox/mapbox-gl-js/issues/4664

@stereobooster

And this is bug from Mapbox GL JS, which does not provide ES6 modules with flow-types stripped. Created ticket mapbox/mapbox-gl-js#4664

Correct, this has been a big headache for react-map-gl from mapbox ~0.26 forward. In fairness to mapbox, this is mainly a problem because react-map-gl v2 uses the internal mapbox Transform class (which is not exported in mapbox's pre-built file for non-browserify bundlers).

There is a postinstall script in react-map-gl v2 to remove flow-types from the mapbox installation, it is slightly sensitive to the relative path of mapbox in node-modules. If this doesn't get run automatically in your install scenario you can always go into node_module/react-map-gl and try to run it manually.

In react-map-gl v3 we were finally able to remove dependencies on internal mapbox files so mapbox's provided pre-built is now sufficient. (Unfortunately it still requires special webpack configuration since mapbox's package.json doesn't set the "main" entry to their pre-built).

Sorry you have to get exposed to all this, one of our goals with react-map-gl v3 is to minimize these complications for new users.

@stereobooster

I switched to webpack 2. Here is example code https://github.com/stereobooster/create-react-app-map-gl/tree/webpack-2

Where are you using webpack 2 here? I see no mention of webpack. Did you push your changes?

  • Are you able to run our stand-alone examples in examples/? They contain the necessary webpack settings you need.

  • You will need to be able to inject the mapbox alias to their pre-built into the webpack config. I checked your app and you do not have any such webpack settings.

  • I took a quick look at create-react-app. Looks nice, but unfortunately, I can't see a way to get at the webpack config. I do find this ominous statement... "You don’t need to install or configure tools like Webpack or Babel. They are preconfigured and hidden so that you can focus on the code."

  • Interestingly, mapbox no longer seems to mention webpack or their prebuilt in their README. We should check their latest version to see if anything has changed in their webpack support (couldn't see anything significant in their CHANGELOG).

@abmai @apercu.

Where are you using webpack 2 here? I see no mention of webpack. Did you push your changes?

From yarn.lock

webpack "2.2.1"

I took a quick look at create-react-app. Looks nice, but unfortunately, I can't see a way to get at the webpack config.

Exactly. This is the best part about create-react-app. It just works. And I do not believe, that there is no way to publish packages that are compatible with CRA. CRA is so good that I use it for projects without React (simply delete React dependencies). This is a breath of fresh air since Rails with it's "convention over configuration"

Connecting dots: mapbox-gl-js will not provide ES6 module until it will not be able to switch to rollup, and it can not switch to rollup because there is no alternative for webworkify. https://github.com/rollup/rollup/issues/1029. See also https://github.com/rollup/rollup/issues/1320

UPD: Other way to do this would be to switch from inline-blob workers to separate file, but this is not supported by CRA at the moment https://github.com/facebookincubator/create-react-app/issues/1277

UPD2: URL.createObjectURL not implemented in jsdom which prevents mapbox-gl to be rendered on server side with react-snapshot. This bug affects even alex3165/react-mapbox-gl/, which works with CRA out of the box.

@stereobooster Thanks for that interesting analysis!

I've came back to looking at using react-map-gl a year on, back when I had all sorts of issues with webpack. I was semi-hopeful that this would have played nice with create-react-app by now but see it's a lot more complicated than that! :face_with_head_bandage: 🔫

Update: MapboxGL now uses ES6 modules https://github.com/mapbox/mapbox-gl-js/pull/6196

For those tracking this issue for the past few months like me, @stereobooster 's comment means react-map-gl now works with CRA without the need to eject. I just tested it with a basic CRA app and one of the examples for react-map-gl 👍 💯

I've added this to config-overrides.js

  config.resolve = {
    alias: {
      'mapbox-gl$': path.join(resolveApp('node_modules'), '/mapbox-gl/dist/mapbox-gl.js'),
    },
  };

It works in development elements all show up properly. But after build, there still being Uncaught ReferenceError: s is not defined or Uncaught ReferenceError: u is not defined.
And elements in the map won't show up, see console of my site.

I have opened a PR documenting a working integration with a Typescript CRA.

For those tracking this issue for the past few months like me, @stereobooster 's comment means react-map-gl now works with CRA without the need to eject. I just tested it with a basic CRA app and one of the examples for react-map-gl 👍 💯

Can you share example with CRA ?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ckalas picture ckalas  ·  5Comments

sicksid picture sicksid  ·  3Comments

joseomar10 picture joseomar10  ·  5Comments

SethHamilton picture SethHamilton  ·  3Comments

miccferr picture miccferr  ·  4Comments