Issue in Ionic production build for Mapbox GL JS feature

Hi All,
I am developing an simple application using ionic 3. Integrating Mapbox GL JS to my application.
In home page, i am viewing the particular location using mapbox.

Using ionic cordova build android or ionic cordova build android --release, i am able to view the map from the output of the build
But for production build i.e ionic cordova build android --prod --release, i am not able to view the map

The same thing happened for browser build.
I am using mapbox GL JS version as mapbox-gl@^0.37.0.

Code snippets taken from the below url
https://www.mapbox.com/mapbox-gl-js/examples/
for display a map.
Is anyone tried out the same?

I would appreciate any help on the same.

Thanks in Advance,

Regards,
Lakshmanan

1 Like

Please share a bit:

  • What is your ionic info output.
  • What is your packages.json content?
  • Does the problem also appear if you only add --prod (and not --release) to the build command?
  • Can you share the code you used to implement this?
  • Did you remote debug the problem on the device already?

Hi Sujan,
Details are

  1. $ ionic info

global packages:

@ionic/cli-utils : 1.4.0
Cordova CLI      : 7.0.1
Ionic CLI        : 3.4.0

local packages:

@ionic/app-scripts              : 1.3.7
@ionic/cli-plugin-cordova       : 1.4.0
@ionic/cli-plugin-ionic-angular : 1.3.1
Cordova Platforms               : android 6.2.3 browser 4.1.0 platforms
Ionic Framework                 : ionic-angular 3.1.1

System:

Node       : v6.10.3
OS         : Windows 10
Xcode      : not installed
ios-deploy : not installed
ios-sim    : not installed
npm        : 4.5.0
  1. Package.json contents
    {
    “name”: “myApp”,
    “version”: “0.0.1”,
    “author”: “Ionic Framework”,
    “homepage”: “http://ionicframework.com/”,
    “private”: true,
    “scripts”: {
    “clean”: “ionic-app-scripts clean”,
    “build”: “ionic-app-scripts build”,
    “lint”: “ionic-app-scripts lint”,
    “ionic:build”: “ionic-app-scripts build”,
    “ionic:serve”: “ionic-app-scripts serve”
    },
    “dependencies”: {
    "@angular/common": “4.1.3”,
    "@angular/compiler": “4.1.3”,
    "@angular/compiler-cli": “4.1.3”,
    "@angular/core": “4.1.3”,
    "@angular/forms": “4.1.3”,
    "@angular/http": “4.1.3”,
    "@angular/platform-browser": “4.1.3”,
    "@angular/platform-browser-dynamic": “4.1.3”,
    "@ionic-native/core": “3.10.2”,
    "@ionic-native/splash-screen": “3.10.2”,
    "@ionic-native/status-bar": “3.10.2”,
    "@ionic/storage": “2.0.1”,
    “cordova-browser”: “^4.1.0”,
    “cordova-plugin-console”: “^1.0.5”,
    “cordova-plugin-device”: “^1.1.4”,
    “cordova-plugin-splashscreen”: “^4.0.3”,
    “cordova-plugin-statusbar”: “^2.2.2”,
    “cordova-plugin-whitelist”: “^1.3.1”,
    “ionic-angular”: “3.4.2”,
    “ionic-plugin-keyboard”: “^2.2.1”,
    “ionicons”: “3.0.0”,
    “mapbox-gl”: “^0.38.0”,
    “rxjs”: “5.4.0”,
    “sw-toolbox”: “3.6.0”,
    “zone.js”: “0.8.12”
    },
    “devDependencies”: {
    "@ionic/app-scripts": “1.3.7”,
    "@ionic/cli-plugin-cordova": “1.4.0”,
    "@ionic/cli-plugin-ionic-angular": “1.3.1”,
    “typescript”: “2.3.3”
    },
    “description”: “An Ionic project”,
    “cordova”: {
    “plugins”: {
    “cordova-plugin-console”: {},
    “cordova-plugin-device”: {},
    “cordova-plugin-splashscreen”: {},
    “cordova-plugin-statusbar”: {},
    “cordova-plugin-whitelist”: {},
    “ionic-plugin-keyboard”: {}
    },
    “platforms”: [
    “browser”
    ]
    }
    }
  2. Getting the same issue with ionic cordova build android --prod
  3. I saw the device logs, but not able to get any info out of that.

Thanks,
K. Lakshmanan

Remote debug on Android: Follow these instructions here to debug the problem in Chrome dev tools: https://ionic.zone/debug/remote-debug-your-app#android Look at the console and network tabs for errors.

@Sujan12,
Code shared in github

Also attached the error screenshot for the browser production build.
Any inputs?

  1. Does it work with ionic serve?
  2. Does it work if you build without --prod as well?

If both is “Yes”, then the problem is the stuff that happens in a --prod build by @ionic/app-scripts (which I don’t know enough about to really be of help).

@Sujan12

  1. It works on ionic serve as well without --prod build.
1 Like

I am able to resolve after some experimentation. Use Mapbox CDN instead of module bundler and modified as per url https://www.mapbox.com/mapbox-gl-js/api/.

Now i am able to verify the production build.
I am yet to understand what is the difference between the Mapbox CDN and module bundler.

Thanks Sujan for your inputs.

4 Likes

So you are now not including mapbox in your package.json any more, but only loading it via a script tag in index.html?

@Sujan12
Yes Sujan. I am using as a script tag.

could you explain what you did?
I still can not get the mapbox maps to load in the --prod build.
I keep getting the ‘e is not defined’ message even if i am including the mapbox js file directly from a script tag.

I also can not get the mapbox gl maps to load in the --prod build.

cli packages:

@ionic/cli-utils  : 1.18.0
ionic (Ionic CLI) : 3.18.0

global packages:

cordova (Cordova CLI) : not installed

local packages:

@ionic/app-scripts : 3.1.0
Cordova Platforms  : android 6.3.0
Ionic Framework    : ionic-angular 3.9.2

System:

Android SDK Tools : 26.1.1
Node              : v6.11.4
npm               : 5.5.1
OS                : Windows 10

package.json contents:

      {
"name": "Mapbox-Gl-maps",
"version": "0.0.1",
"author": "Ionic Framework",
"homepage": "http://ionicframework.com/",
"private": true,
"scripts": {
  "clean": "ionic-app-scripts clean",
  "build": "ionic-app-scripts build",
  "lint": "ionic-app-scripts lint",
  "ionic:build": "ionic-app-scripts build",
  "ionic:serve": "ionic-app-scripts serve"
},
"dependencies": {
  "@angular/common": "5.0.0",
  "@angular/compiler": "5.0.0",
  "@angular/compiler-cli": "5.0.0",
  "@angular/core": "5.0.0",
  "@angular/forms": "5.0.0",
  "@angular/http": "5.0.0",
  "@angular/platform-browser": "5.0.0",
  "@angular/platform-browser-dynamic": "5.0.0",
  "@ionic-native/core": "4.3.3",
  "@ionic-native/splash-screen": "4.3.3",
  "@ionic-native/status-bar": "4.3.3",
  "@ionic/storage": "2.1.3",
  "cordova-android": "6.3.0",
  "cordova-plugin-compat": "^1.2.0",
  "cordova-plugin-device": "^1.1.4",
  "cordova-plugin-geolocation": "^2.4.3",
  "cordova-plugin-ionic-webview": "^1.1.16",
  "cordova-plugin-splashscreen": "^4.0.3",
  "cordova-plugin-whitelist": "^1.3.1",
  "ionic-angular": "3.9.2",
  "ionic-plugin-keyboard": "^2.2.1",
  "ionicons": "3.0.0",
  "rxjs": "5.5.2",
  "sw-toolbox": "3.6.0",
  "zone.js": "0.8.18"
},
"devDependencies": {
  "@ionic/app-scripts": "3.1.0",
  "mapbox-gl": "^0.41.0",
  "typescript": "2.4.2"
},
"description": "An Ionic project",
"cordova": {
  "plugins": {
    "ionic-plugin-keyboard": {},
    "cordova-plugin-whitelist": {},
    "cordova-plugin-device": {},
    "cordova-plugin-splashscreen": {},
    "cordova-plugin-ionic-webview": {},
    "cordova-plugin-geolocation": {}
  },
  "platforms": [
    "android"
  ]
}

}

I have based on this example (until the section “Add the Map code to homepage”):

home.ts:

import mapboxgl from 'mapbox-gl';
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  constructor(public navCtrl: NavController) { }

  ionViewDidEnter() {    
    mapboxgl.accessToken = '<TOKEN_ID>';
    var map = new mapboxgl.Map({
      style: 'mapbox://styles/mapbox/light-v9',
      center: [-74.0066, 40.7135],
      zoom: 16,
      pitch: 80,
      minZoom: 7.5,
      maxZoom: 17,
      container: 'map'
    });
    
  }

}

In change this line in the example post:

import mapboxgl from 'mapbox-gl/dist/mapbox-gl.js'

for this other:

import mapboxgl from 'mapbox-gl';

home.html:

<ion-header>
   <ion-navbar>
       <ion-title>Home</ion-title>
   </ion-navbar>
</ion-header>
<ion-content padding>
      <div id='map'></div>
</ion-content>

index.html (include js and CSS by CDN):

<!-- cordova.js required for cordova apps (remove if not needed) -->
<script src="cordova.js"></script>
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v0.41.0/mapbox-gl.js"></script>
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.41.0/mapbox-gl.css" rel="stylesheet" />

With “ionic cordova run android” app runs OK
But with “ionic cordova run android --prod” I also keep getting the ‘e is not defined’ message

I can not delete “mapbox-gl”: “^0.41.0” in devDependencies of package.json because I get an comipile error.

Same problem here.

However I found a solution for an angular application (angular-cli).

 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 @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.

But in Ionic we don’t have .angular-cli.json so I don’t know

Maybe Ionic should allow something similar for cases like this, to be able to adjust obfuscation / minimization.

In another web application with webpack (without Ionic) I had problems with mapbox GL in prod mode, but I could solve them by being able to deactivate some minimizations and obfuscations.

I solved the problem by using CDN mapbox in index.html :

<link rel="stylesheet" href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.41.0/mapbox-gl.css">
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v0.41.0/mapbox-gl.js"></script>

And in my typescript file :

import ...
declare var mapboxgl;
import ...
3 Likes

Checked, this allows a correct operation in production mode
Thank you

I stumbled across this topic with the same problem. My conclusion is that you are not allowed to use the --minifyjs flag (which is also active when using --prod). In my case I wasn’t able to get pbf data but I was able to load png files. I guess something breaks in the js code when doing the minifyjs. It took me nearly a day to find out. As as side-effect I learned alot about SSL and all the stuff you can configure on a nginx server and how building an APK works in cordova. In the end the real problem was only one flag…

Thanks it is working perfectly in android and ios.

after setting script in the index.html? how do you declare on any of the other pages? wont you need to import it? or its alrready available?