angular-cli: mapboxgl is incompatible with the CLI in a production build

Bug Report or Feature Request (mark with an x)

- [x] bug report -> please search issues before submitting
- [ ] feature request

It seems that using Mapbox GL and Angular CLI when targeting production does not work.

Running an app that imports Mapbox with import * as mapboxgl from 'mapboxgl' via ng serve seems to work just fine. But if you run it via:

ng serve --open --sourcemap --target=production --output-hashing=all

An error is thrown from one of the workers created by Mapbox.

Versions.

@angular/cli: 1.0.0-rc.4
node: 7.4.0
os: darwin x64
@angular/common: 2.4.10
@angular/compiler: 2.4.10
@angular/core: 2.4.10
@angular/flex-layout: 2.0.0-rc.1
@angular/forms: 2.4.10
@angular/http: 2.4.10
@angular/material: 2.0.0-beta.2
@angular/platform-browser: 2.4.10
@angular/platform-browser-dynamic: 2.4.10
@angular/router: 3.4.10
@angular/cli: 1.0.0-rc.4
@angular/compiler-cli: 2.4.10
@angular/tsc-wrapped: 0.5.2

Repro steps.

  1. Scaffold an Angular CLI app
  2. Add Mapbox GL dep "mapbox-gl": "^0.34.0"
  3. Add the typings ("@types/mapbox-gl": "^0.30.0")
  4. import * as mapboxgl from 'mapboxgl' anywhere in the app (log mapboxgl just to see the output)
  5. Create a map in one of the components const map: mapboxgl.Map = new Map(Object.assign({container: element})); (element is the nativeElement from @ViewChild('map', {read: ElementRef}) mapRef: ElementRef)

The log given by the failure.

blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1 Uncaught ReferenceError: e is not defined
33../support/isBuffer @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
o @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
(anonymous) @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
102.util @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
o @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
(anonymous) @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
128.../error/validation_error @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
o @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
(anonymous) @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
142../reference/latest @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
o @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
(anonymous) @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
156.../style-spec/validate_style.min @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
o @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
(anonymous) @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
148.../style-spec/reference/latest @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
o @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
(anonymous) @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
154.../style-spec/feature_filter @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
o @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
(anonymous) @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
98.../style/style_layer_index @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
o @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
(anonymous) @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
anonymous @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:3
o @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
t @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1
(anonymous) @ blob:https://ds.infarm.com/e940fbf0-8c73-42bf-a3cd-d5326c57e0f6:1

Desired functionality.

An app using Mapbox should work when building for production.

Mention any other details that might be useful.

If I instead load Mapbox via .angular-cli.json:

"styles": [
    "../node_modules/mapbox-gl/dist/mapbox-gl.css"
],
"scripts": [
    "../node_modules/mapbox-gl/dist/mapbox-gl.js"
]

It works as expected. I suspect it might have something to do with minification or some other transformation applied to one of the mapbox scripts.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 8
  • Comments: 54 (12 by maintainers)

Commits related to this issue

Most upvoted comments

I think I have a solution to this issue…

My setup:

@angular/cli: 1.2.1
node: 6.9.5
os: darwin x64
@angular/animations: 4.3.0
@angular/cdk: 2.0.0-beta.8
@angular/common: 4.3.0
@angular/compiler: 4.3.0
@angular/core: 4.3.0
@angular/flex-layout: 2.0.0-rc.1
@angular/forms: 4.3.0
@angular/http: 4.3.0
@angular/material: 2.0.0-beta.8
@angular/platform-browser: 4.3.0
@angular/platform-browser-dynamic: 4.3.0
@angular/router: 4.3.0
@angular/cli: 1.2.1
@angular/compiler-cli: 4.3.0
@angular/language-service: 4.3.0

Install mapbox-gl (note that this is just to get the prebuilt js and css files in /dist. The source is not used) (my version is mapbox-gl@0.39.1): npm install --save mapbox-gl

Install mapbox-gl types (my version is @types/mapbox-gl@0.39.4): npm install --save @types/mapbox-gl

Very important - this is the key step Edit tsconfig.app.json and change the compilerOptions/types line: types: ["mapbox-gl", "geojson"]

Edit tsconfig.spec.json and change the compilerOptions/types line: types: [“mapbox-gl”, “geojson”, “jasmine”, “node”]

This enables automatic inclusion of the required types from the @types packages

Add the pre-built mapbox js and css to your .angular-cli.json config:\

...
"styles": [
        "styles.scss",
        "../node_modules/mapbox-gl/dist//mapbox-gl.css"
      ],
      "scripts": [
        "../node_modules/mapbox-gl/dist/mapbox-gl.js"
      ]
...

Now make sure that you have no import * as mapbox from 'mapbox-gl' statements anywhere in your codebase. You should be able to use mapbox with full typing like this e.g mapboxgl.Map, mapboxgl.LngLat. Geojson types are also pulled in e.g. GeoJSON.FeatureCollection<GeoJSON.GeometryObject>

Note that if you forget and leave any import * as mapbox from 'mapbox-gl' statements in your codebase then you will end up with 2 copies of mapboxgl - 1 from the script inclusion, and 1 built from the source. However, the 1 from the script inclusion seems to be loaded after so it will still work ok but the size of your app will be bigger.

Detailled cause of the issue : https://github.com/mapbox/mapbox-gl-js/issues/4359#issuecomment-303880888 A better workaround is to set noParse: /(mapbox-gl)\.js$/, to the webpack config.

@filipesilva Is there a way to set noParse conf without ejecting ?

Upgrading to mapbox-gl.js 0.48.0 fixes this error if anyone still experiences this. I got it suddenly after moving to angular 6.1

@Wykks the reason it fails on ng serve but not on build is because webpack-dev-server actually needs node.global = true since it bundles sockjs-client.

I’m trying to address the node.global problem in https://github.com/webpack/webpack-dev-server/issues/1147 and https://github.com/sockjs/sockjs-client/issues/401#issuecomment-336904363.

Using @angular/cli 1.5.0-rc.0 ng build --prod with global: true => Broken

chunk {0} polyfills.d8d3d78a4deb2ab66856.bundle.js (polyfills) 66.1 kB {4} [initial] [rendered]
chunk {1} main.d84a5e65a523d900e3b6.bundle.js (main) 980 kB {3} [initial] [rendered]
chunk {2} styles.cbb57e89e9ac6ad6f3fb.bundle.css (styles) 78.1 kB {4} [initial] [rendered]
chunk {3} vendor.23b050bcb59f7435f7a8.bundle.js (vendor) 1.09 MB [initial] [rendered]
chunk {4} inline.6eda527e2fab8b0dae50.bundle.js (inline) 1.45 kB [entry] [rendered]

ng build --prod with global: false => App works 👍 Size info :

chunk {0} polyfills.7e3abfc710733c67257a.bundle.js (polyfills) 65.9 kB {4} [initial] [rendered]
chunk {1} main.d84a5e65a523d900e3b6.bundle.js (main) 980 kB {3} [initial] [rendered]
chunk {2} styles.cbb57e89e9ac6ad6f3fb.bundle.css (styles) 78.1 kB {4} [initial] [rendered]
chunk {3} vendor.3274e60605db088741dd.bundle.js (vendor) 1.09 MB [initial] [rendered]
chunk {4} inline.f341fd26bb21d3c849c9.bundle.js (inline) 1.45 kB [entry] [rendered]

ng serve --prod with global: false => Uncaught ReferenceError: global is not defined ng serve with global: false => Uncaught ReferenceError: global is not defined at eval [...]node_modules/sockjs-client/lib/utils/browser-crypto.jsbrowser-crypto.js:3) ng build --prod --build-optimizer with global: false => App works 👍

chunk {0} polyfills.7e3abfc710733c67257a.bundle.js (polyfills) 65.7 kB {3} [initial] [rendered]
chunk {1} main.c7a84c385043ae0584ac.bundle.js (main) 1.92 MB {3} [initial] [rendered]
chunk {2} styles.cbb57e89e9ac6ad6f3fb.bundle.css (styles) 78.1 kB {3} [initial] [rendered]
chunk {3} inline.a3c784b219c2d2710d57.bundle.js (inline) 1.45 kB [entry] [rendered]

By the way the proj tested is right there : https://github.com/Wykks/ngx-mapbox-gl (That’s why this issue is critical for me)

@j-slvr discarded, the other solutions are better than noParse