Skip to main content

Using a bundler

This guide covers configuration options for using Mapbox GL JS with module bundlers such as Webpack, Rollup, or Vite.

ESM entry point

Mapbox GL JS ships an ES module entry point at mapbox-gl/esm. Using this entry point is recommended for modern build toolchains because it enables native ES module semantics, including tree-shaking support that can reduce your final bundle size. To use the ESM bundle you must be on Mapbox GL JS v3.25.0 or later.

There are 2 key differences from the default entry point:

  • how you import the package
  • how you set the access token.

Import statement

Use a namespace import to bring in the mapboxgl object:

import * as mapboxgl from 'mapbox-gl/esm';
import 'mapbox-gl/dist/mapbox-gl.css';

Using a namespace import preserves the familiar mapboxgl.* API — every class and method is accessed the same way as before. It also keeps call sites self-documenting: mapboxgl.Map, mapboxgl.Marker, and mapboxgl.setWorkerCount all carry their origin with them, so the context is never lost as your codebase grows.

Tip

The CSS file still needs to be imported separately regardless of which entry point you use.

Setting the access token

The mapboxgl.accessToken = '...' setter no longer works with the ESM entry point because ESM Module Namespace Objects are read-only by spec. To set your access token with the ESM bundle, pass your access token via the Map options object instead:

const map = new mapboxgl.Map({
accessToken: 'YOUR_MAPBOX_ACCESS_TOKEN',
container: 'map',
center: [-74.5, 40],
zoom: 9
});

Using the namespace import mirrors the familiar mapboxgl.* API, so the only changes needed in existing code are updating the import line and passing your access token via the Map options object.

Note

Named imports are also available from mapbox-gl/esm, for example import { Map } from 'mapbox-gl/esm'. We recommend the namespace import because it preserves API context at call sites and avoids shadowing native JavaScript globals like Map.

Transpiling

Starting with version 2, Mapbox GL JS is distributed as an ES6-compatible JavaScript bundle. It uses syntax and APIs from modern JavaScript specifications and is compatible with all major modern browsers.

The JavaScript bundle is incompatible with some transpiler transforms because of the way it shares code between the main thread and Web Worker. We do this to reduce the bundle size and improve rendering performance. If you are using Mapbox GL JS v2 or newer with a module bundler such as Webpack or Rollup along with a transpiler such as Babel, there are three ways to make it compatible:

  • Use browserslist to target transpilation to a set of compatible transforms
  • Explicitly disable transpiling of the Mapbox GL JS bundle
  • Load and transpile Web Worker code separately at the cost of increasing bundle size and reducing performance

Targeting transpilation with browserslist

If you're using a build tool that supports browserslist such as @babel/preset-env, you can align your list with the Mapbox GL JS .browserslistrc.

This list can be specified in your project's package.json or in a .browserslistrc file. See the @babel/preset-env docs for more details.

Excluding Mapbox GL JS from transpilation

If other parts of your application need ES5 transpilation, consider excluding GL JS explicitly. If you are using Webpack, use the ! prefix in the import statement to exclude mapbox-gl from being transformed by existing loaders. See the Webpack loaders inline usage docs for more details.

import mapboxgl from '!mapbox-gl';

Or configure this centrally in webpack.config.js by adding the ignore option to Babel:

use: {
loader: 'babel-loader',
options: {
presets: ['my-custom-babel-preset'],
ignore: ['./node_modules/mapbox-gl/dist/mapbox-gl.js']
}
}

Loading and transpiling the Web Worker separately

If your application requires ES5 compatibility, your module bundler needs to be configured to load and transpile Mapbox GL JS's Web Worker separately. This comes at the cost of significantly increasing the bundle size and negatively impacting rendering performance — only do this if you have a strong need for supporting legacy browsers.

If you are using Webpack, configure worker-loader inline when importing mapbox-gl:

import mapboxgl from 'mapbox-gl/dist/mapbox-gl-csp';
import MapboxWorker from 'worker-loader!mapbox-gl/dist/mapbox-gl-csp-worker';

mapboxgl.workerClass = MapboxWorker;
const map = new mapboxgl.Map({
container: 'map',
center: [-74.5, 40],
zoom: 9
});

Or configure worker-loader centrally in webpack.config.js:

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

Then wire up the worker in your application code:

import mapboxgl from 'mapbox-gl/dist/mapbox-gl';
import MapboxWorker from 'mapbox-gl/dist/mapbox-gl-csp-worker';

mapboxgl.workerClass = MapboxWorker;
const map = new mapboxgl.Map({
container: 'map',
center: [-74.5, 40],
zoom: 9
});

To test client support for your applications, see the Check Mapbox GL JS browser support example.

Was this page helpful?