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

Uncaught ReferenceError: m is not defined - Create React App - browserslist - Internet Explorer IE #1011

Closed
jirihajek opened this issue Feb 18, 2022 · 28 comments
Labels
bug Something isn't working

Comments

@jirihajek
Copy link

Hi, I'm trying to replace mapbox-gl and while it works fine in the developer mode, it breaks down when compiled into production using standard react-scripts.

maplibre-gl-js version: 2.1.6

I just use it like:

import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';

new maplibregl.Map({});

The map is properly drawn, but when compiled, I get error message:

Uncaught ReferenceError: m is not defined
    at 715727c0-8b17-4de1-9814-b138884d408b:1:6514

from the workers and nothing is drawn. I'm not sure it's a bug, I suppose I might be doing something wrong, but don't see anything obvious, as the same approach works with mapbox-gl. Thanks for any idea!

@HarelM
Copy link
Member

HarelM commented Feb 18, 2022

No clue, try reproducing this in stackbliz.

@jirihajek
Copy link
Author

jirihajek commented Feb 18, 2022

I tried stackblitz, but it doesn't seem to be able to handle a 'build' command in order to test the production environment. Anyway, I created a trivial new project, just a clean create-react-app application with a simple map:

import { useEffect } from 'react';
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import './App.css';

function App() {
  useEffect(() => {
    const mbMap = new maplibregl.Map({
      container: 'map',
    });
    mbMap.setStyle('https://api.maptiler.com/maps/bright/style.json?key=******************');
  });

  return (
    <div className="App">
       <div style={{width: 400, height: 300}} id='map'/>
    </div>
  );
}

export default App;

And the result is the same: Works in development, but as soon as it's compiled using npm run build, there's the same runtime error and the map isn't drawn.

@HarelM
Copy link
Member

HarelM commented Feb 18, 2022

I'm not familiar enough with react to understand the differences between dev and prod build.
I suggest to try and use the react library instead of writing your own...

@Kanahiro
Copy link
Contributor

IMHO you should use useRef() to indentify HTMLDivElement.
Following is simple sample.

const Map: React.FC = () => {
    const mapContainer = useRef<HTMLDivElement | null>(null);

    useEffect(() => {
        if (!mapContainer.current) return;

        const map = new mapboxgl.Map({
            container: mapContainer.current,
            style: 'https://api.maptiler.com/maps/bright/style.json?key=******************',
        });
    }, []);
    return <div style={{ height: 800 }} ref={mapContainer} />;
};
export default Map;

Also, I think this wouldn't be a problem on maplibre-gl-js.

@jirihajek
Copy link
Author

IMHO you should use useRef() to indentify HTMLDivElement.

Thanks, you're right that it's a cleaner approach, but tried it and it doesn't have any effect, the problem remains the same.

I'm not familiar enough with react to understand the differences between dev and prod build.

I'm not an expert in this field either, but afaik we are talking mostly just about webpack applied to the project. That's what I suppose many projects do and that's why I'm surprised that I'm the only one reporting this issue.

I suggest to try and use the react library instead of writing your own...

Do you mean any particular one? I'd give it a try, but to be honest, I don't see a reason why I'd get any different result after I apply webpack than I get in the sample project above. (not mentioning that I'm not sure I'd be able to use another library due to the ways I use the map - but that's beyond the scope of this issue and the sample project)

@HarelM
Copy link
Member

HarelM commented Feb 21, 2022

The following is what I know is the goto when it comes to React:
https://github.com/visgl/react-map-gl
I've seen the following issue which seems to make sure maplibre is working with this library:
visgl/react-map-gl#1685
So I think people there are able to make maplibre work.
It might require some extra configuration, IDK...
If you know what causing this problem in this library feel free to send a PR. I'm not sure I know where to begin...

@jirihajek
Copy link
Author

https://github.com/visgl/react-map-gl

I tried a simple project and I got the very same problem. For the reference, it's like this:

import * as React from 'react';
import Map from 'react-map-gl';
import maplibregl from 'maplibre-gl';

function App() {
  return <Map 
    mapLib={maplibregl} 
    style={{width: 600, height: 400}}
    mapStyle="https://api.maptiler.com/maps/bright/style.json?key=**************"
  />;
}

export default App;

If you know what causing this problem in this library feel free to send a PR. I'm not sure I know where to begin...

I tried to find out more. The development webpack build apparently works fine, but the production build is where it breaks. I tried to pinpoint the issue, used webpack without minification and the error message is now

Uncaught ReferenceError: _wrapNativeSuper is not defined

and after some search I found that it's from the ajax.ts:

export class AJAXError extends Error {
    /**
     * The response's HTTP status code.
     */
    status: number;

    /**
     * The response's HTTP status text.
     */
    statusText: string;

    /**
     * The request's URL.
     */
    url: string;

    /**
     * The response's body.
     */
    body: Blob;

    constructor(status: number, statusText: string, url: string, body: Blob) {
        super(`AJAXError: ${statusText} (${status}): ${url}`);
        this.status = status;
        this.statusText = statusText;
        this.url = url;
        this.body = body;
    }
}

Any idea?

@RowanTate
Copy link

I'm having the same issue. My guess it's something to do with how Create React App is doing its bundling/minifying. But I don't understand enough of how that process works

@RowanTate
Copy link

RowanTate commented Mar 3, 2022

Digging a bit deeper in to this, it is related to what browser/js features are being targeted at (not sure the exact feature that causes the issue)
But I found if you change the browserslist being targeted in the package.json to something modern maplibre-gl works correctly.

This is why development builds work, but productions builds don't. Buy default CRA has a very wide browsers support for production but very restricted for development

For example if you change your browserslist to something like the following, this will make your production build work (at least for the latest version of chrome)
"browserslist": { "production": [ "last 1 chrome version" ],

Not sure what the best solution here is?

Would be good to know the exact feature that causes the change in the transpiling (ie what browsers we are unable to target)
Possibly related to class usage? https://babeljs.io/docs/en/babel-plugin-transform-classes

@wipfli
Copy link
Member

wipfli commented Mar 19, 2022

Thanks for the hint about broswerslist. If I add internet explorer to the development section in my package.json, I get the ReferenceError also in development mode:

  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version",
+     "ie 11"
    ]
  }

@wipfli
Copy link
Member

wipfli commented Mar 19, 2022

Note that MapLibre GL JS v2 dropped IE support altogether.

@wipfli
Copy link
Member

wipfli commented Mar 19, 2022

I ended up using the following package.json

{
  "name": "maplibre-v2",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.2",
    "@testing-library/react": "^12.1.4",
    "@testing-library/user-event": "^13.5.0",
    "maplibre-gl": "^2.1.7",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "5.0.0",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
-     ">0.2%",
-     "not dead",
-     "not op_mini all"
+     "defaults",
+     "not ie 11"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Note that I use react-scripts@5.0.0. I had issues with lower versions.

@wipfli wipfli changed the title Uncaught ReferenceError: m is not defined Uncaught ReferenceError: m is not defined - Create React App - browserslist - Internet Explorer IE Mar 19, 2022
@jirihajek
Copy link
Author

Thanks for the updates, I can confirm that the change in targeted browsers really resolves the issue. In my case though, it was necessary to also include "not op_mini all", without this the issue was still there.

A note to anybody testing this: You might need to delete node_modules/.cache, otherwise the change in "browserslist" might not be applied.

That said, the underlaying cause of the issue is still unclear.

@ohrie
Copy link

ohrie commented Apr 6, 2022

I can confirm, that adding browserslist to package.json using ["defaults", "not ie 11"] fixed the issue in Gatsby 4.

@theweaklink
Copy link

Hi there,

I am getting a similar error y is not defined when building my app (made with create-react-app too). I followed this mapboxgl issue replacing the path to the correct maplibre-gl worker, but no luck.

  • In dev (yarn start) => no issue at all, the map displays properly
  • Without the worker-loader trick => creating a build (yarn build) in dev and production works however map does not display and y is not defined error is output
  • With the worker-loader trick => the build doesn't go through
Module parse failed: 'import' and 'export' may appear only with 'sourceType: module' (1:0)
File was processed with these loaders:
 * ./node_modules/worker-loader/dist/cjs.js
 * ./node_modules/babel-loader/lib/index.js
 * ./node_modules/source-map-loader/dist/cjs.js
You may need an additional loader to handle the result of these loaders.
> export default function Worker_fn() {
|   return new Worker(__webpack_public_path__ + "static/js/maplibre-gl-csp-worker.10c64516.worker.js");
| }

I'm not sure if this is related to this issue (it looks like it overlaps?).
Thanks

@theweaklink
Copy link

theweaklink commented Apr 13, 2022

Actually after fiddling a bit and crossing info from docs and github issues, I eventually got it to work in both dev and prod env. Here is what worked in case it helps anyone else:

package.json

    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
      "not op_mini all",
      "defaults",   # line added as mentionned above in this issue
      "not ie 11"   # line added as mentionned above in this issue
    ],

in App.js (or wherever the map import is)

// eslint-disable-next-line import/no-webpack-loader-syntax
import maplibregl from '!maplibre-gl';      // ! is important here
import maplibreglWorker from 'maplibre-gl/dist/maplibre-gl-csp-worker';

maplibregl.workerClass = maplibreglWorker;

@jirihajek
Copy link
Author

Just to clarify, I guess that the workerClass tweak isn't needed after you modify browserslist, or is it?

@theweaklink
Copy link

On my end it is still needed: I just tried again.

  • with browserslist tweak only: building the app goes through however when serving it statically, I get the error m is not defined
  • with both browserlist and workerClass tweaks: building and serving statically the app are both working well.

(I am using maplibre-gl@2.1.9)

@Deathis
Copy link

Deathis commented Apr 28, 2022

weblibregl doesn't have workerClass attribute. I'm using maplibre-gl@2.1.9+ react + typescript

@jirihajek
Copy link
Author

Fyi, now I also need the workerClass trick in order to avoid the m is not defined error. I suppose some packages got updated in my enviroment, since originally the browserlist tweak was enough to get it working.

@apresmoi
Copy link

apresmoi commented May 20, 2022

I'm using Gatsby 3.x. Adding the browserlist wasn't enough. I had to update maplibre-gl to the latest version and then change my implementation from:

import { Map } from "maplibre-gl";

to

//@ts-ignore
import maplibregl from "!maplibre-gl";
//@ts-ignore
import maplibreglWorker from "maplibre-gl/dist/maplibre-gl-csp-worker";
//@ts-ignore
maplibregl.workerClass = maplibreglWorker;

//Since I'm using typescript I have to import this one like this to be able to type the map variable
import { Map } from "maplibre-gl"; 

then you must initialize the map using:

const map: Map = new maplibregl.Map({ ... })

Thanks everyone !

@alanpilloud
Copy link

@apresmoi solutions worked for me too, using Gatsby 4.

Thanks a lot !

@VictorVelarde
Copy link

VictorVelarde commented Jul 14, 2022

Thx a lot @apresmoi and @theweaklink
Your modifications worked also in my case (using import { Map } from 'react-map-gl';, in a create react app v4 project)

@HarelM
Copy link
Member

HarelM commented Aug 21, 2022

This seems to have been solved. Closing.

@HarelM HarelM closed this as not planned Won't fix, can't repro, duplicate, stale Aug 21, 2022
@HarelM HarelM added the bug Something isn't working label Aug 21, 2022
@jirihajek
Copy link
Author

I don't think that this issue should be closed yet. Not being able to be successfully compiled by Webpack is imho still an issue that we should try to find a real solution to. It's good that we have a workaround now, but it isn't a solution.

@HarelM
Copy link
Member

HarelM commented Aug 23, 2022

I'm able to compile maplibre with angular that uses webpack.
The problem is not with this library, it might be webpack configuration or other stuff...

YuChunTsao added a commit to BanNel/tm-welfare-map that referenced this issue Sep 5, 2022
- Create POI and company layer components
- Add all icons to map
- Fetch POI data from geojson file
- Fix bug maplibregl, react bug in production
  - [bug issue and solution](maplibre/maplibre-gl-js#1011 (comment))
helllth added a commit to topicmaps-wuppertal/techdemo that referenced this issue Sep 20, 2022
viliket added a commit to viliket/live-trains-finland that referenced this issue Nov 6, 2022
paulgirard added a commit to Universite-Gustave-Eiffel/lasso that referenced this issue Nov 15, 2022
@rmjwilbur
Copy link

rmjwilbur commented Jan 15, 2023

Was getting the following error using current versions: Uncaught ReferenceError: g is not defined on maps when deployed

The suggestion offered by @wipfli worked for me. Switched to a .browserslistrc containing:

`
# NOTE: Need to occasionally run "npm run browserslist" to update caniuselite

# NOTE: Was getting an error: Uncaught ReferenceError: g is not defined on maps when deployed
# Resolved by changing production settings as per #1011

[production]
defaults
not ie 11

[development]
last 1 chrome version
last 1 firefox version
last 1 safari version
`

I doubt switching to .browserslistrc made a difference but I took the opportunity to get this config out of my package.json

cioddi added a commit to mapcomponents/react-map-components-maplibre-cra-template that referenced this issue Feb 5, 2023
@lucaswoj
Copy link
Contributor

Just in case anyone else runs into this issue, it is related to this upstream bug browserslist/browserslist#374, and the minimal fix is to add not android 4.4.3-4.4.4 to your browserslist settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests