mapbox / mapbox-gl-js

Interactive, thoroughly customizable maps in the browser, powered by vector tiles and WebGL
https://docs.mapbox.com/mapbox-gl-js/
Other
11.2k stars 2.22k forks source link

How to reduce bundle size of mapbox-gl? #6320

Closed Stupidism closed 6 years ago

Stupidism commented 6 years ago

I'm using create-react-app. image As you can see, the size of mapbox-gl is over a quater of my app.

mourner commented 6 years ago

We're working very hard on keeping the bundle as small as possible, but the fact is Mapbox GL is an extremely complicated piece of software that has to be somewhat big. We recently managed to reduce it a bit in #6196 (to 148KB minified/gzipped), but we can't get much lighter than that.

Stupidism commented 6 years ago

It's huge progress from 500KB to 148KB! Is it released yet?

Scarysize commented 6 years ago

@Stupidism The current release already is only 168kb (gzipped & minified). What you are showing in your screenshot above is the unminified version.

Check the size here: https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.js

sheerun commented 6 years ago

Maybe you could release few bundles with heavy features disabled?

Cam commented 5 years ago

This should be reopened. The minified version is 671KB. That's too big for most projects.

mourner commented 5 years ago

The current bundle is 169 KB minified / gzipped, but the size is justified given the enormous complexity of the project. We put a lot of effort into keeping it as small as possible, but you can't get much lower than this. We might consider modularizing the build, but it's not like there are several "heavy" features that take a lot of size — it's just that there are hundreds of little things that aren't easy to take away but add up, so modularizing won't help much.

If you're up to exploring the bundle size yourself, please welcome! Maybe you'll find something we haven't thought of yet — we're looking forward to any PRs with improvements.

Cam commented 5 years ago

It's not always possible to use a gzipped resource. So realistically the library does currently come in at 671KB.

I don't think anyone is denying the complexity or criticising the current work. It's great work. It is however quite heavy. Especially when only basic features are required for a project.

Right now I'm having to switch to an alternative due to the weight of the entire library. I'd much prefer to be using Mapbox GL.

Personally I think I modularised library makes a lot of sense. Surely (though, as one who doesn't like to assume, I'd hope this is taken as "hopefully") elements like user geolocating and directions are substantial components.

I'm far from being an expert in either this library or the modularisation of modern Javascript. But I'll certainly try to find time to take a look at some point.

EDIT: I personally think this is an issue that should be left open until some resolution is found.

cs09g commented 5 years ago

It's a bit side from the bundle size thing, but one .pbf size is about 50kb(huge) already, so the library for 500kb with powerful functionalities is somewhat fair enough. But if it could be lighter, much better. and I believe there must be a way of splitting the library.

olso commented 5 years ago

Screenshot 2019-07-04 at 12 04 37

This is too big, what are the alternatives here?

mourner commented 5 years ago

This is too big, what are the alternatives here?

@olso the alternative is to use ordinary raster tiles and Leaflet.

Surely (though, as one who doesn't like to assume, I'd hope this is taken as "hopefully") elements like user geolocating and directions are substantial components.

@Cam unfortunately not. GL JS doesn't have a directions component (there is a plugin though), and geolocation is a native browser API around which GL JS has a very tiny wrapper. We will try to modularize the code in future, but it's unlikely to bring much bundle size benefit — most code is taken by all the logic necessary to render basic components of a base map (lines, polygons, labels and icons).

ChristAsselin commented 5 years ago

This is too big, what are the alternatives here?

@olso the alternative is to use ordinary raster tiles and Leaflet.

@mourner This isn't an alternative if we require using Map Load instead of tiles. :(

olso commented 4 years ago

Hmm https://bundlephobia.com/result?p=mapbox-gl@1.9.0-beta.1

mourner commented 4 years ago

@olso if you look closely, you can notice that 1.9.0 actually got a little smaller than 1.8.1 despite bringing some really cool new features like the within expression.

MSkred commented 4 years ago

35M ./node_modules/mapbox-gl

olso commented 4 years ago

I've just applied lazy loading and separated mapbox into its own chunk

MSkred commented 4 years ago

@oslo How ? Do you have an example ?

olso commented 4 years ago

combination of https://loadable-components.com/ and https://github.com/twobin/react-lazyload

and https://hackernoon.com/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758

MSkred commented 4 years ago

@oslo I'm working with mapbox with the nuxt.js framework and I can't deploy my project because my zip is too heavy... The seconde biggest module is mapbox with 35 fu**ing MB……… I'm fighting with module mapbox for find an solution for minimize her size. The best solution actually is to not use npm i mapboxgl but to work with the cdn…………… But I'm not sure is a good idea for the user exprience

MSkred commented 4 years ago

Any better idea then to use cdn ?

mourner commented 4 years ago

@MSkred the NPM distribution contains many versions of the bundle — development, production, unminified production, strict-csp-compatible, original source code with flow types, etc. In your deployment script, you could just delete everything from node_modules/mapbox-gl except dist/mapbox-gl.js and dist/mapbox-gl.css which are 760KB combined (uncompressed).

MSkred commented 4 years ago

@mourner Thanks a lot ! If someone want the command

cd node_modules
sudo ln mapbox-gl/dist/mapbox-gl.js mapbox-gl/dist/mapbox-gl.css ./
rm -rf mapbox-gl
mkdir -p mapbox-gl/dist
mv mapbox-gl.js mapbox-gl.css mapbox-gl/dist
cd ..
stevepepple commented 4 years ago

@MSkred the NPM distribution contains many versions of the bundle — development, production, unminified production, strict-csp-compatible, original source code with flow types, etc. In your deployment script, you could just delete everything from node_modules/mapbox-gl except dist/mapbox-gl.js and dist/mapbox-gl.css which are 760KB combined (uncompressed).

This was a great suggestion and major help. Thanks @mourner !

Radiergummi commented 4 years ago

@mourner Granted I'd just like to show a fancy map with a few markers here and there, that's zoomable and pan-able, is there a more lightweight option available? Or did I just sum up the complex parts? 😄
We're going to use MapBox maps for some really cool stuff in some specific places of our application, but for the most part, it's just plain boring maps. Bundling the full MapBox GL library seems overkill; it's not just the bundle size, but the sheer time it takes the engine to evaluate and parse all that code (results from Lighthouse, ?optimize=true added to map style):

URL Total CPU Time Script Evaluation Script Parse
/mapbox.53312cd.js (app.example.com) 1,803 ms 1,657 ms 26 ms

Edit: For clarification, that's the webpack chunk for mapbox, probably got a bit of glue code in it, but that's negligible.

peterhil commented 2 years ago

We're working very hard on keeping the bundle as small as possible, but the fact is Mapbox GL is an extremely complicated piece of software that has to be somewhat big. We recently managed to reduce it a bit in #6196 (to 148KB minified/gzipped), but we can't get much lighter than that.

This issue should absolutely be reopened, and you definitely can make the library footprint smaller by using named exports.

Very compelling reasons to use named exports and avoid default exports like the plague: https://stackoverflow.com/a/68665805/470560

I am in the process of moving Treebuddy's maps away from Leaflet and d3.js, and into new vector based Mapbox APIs.

I was shocked to find that importing mapboxgl and manually splitting it into separate chunk was 872 KB after minification in production build with Rollup! IMHO, a reasonable size for libraries is under 40 KB, and preferably 500B-12 KB per component!

The reason is that the only export is the default export from mapboxgj/index.js, and that prevents tree shaking. Please export individual components and functions.

You should be able to only import the bare minimum with import { mapbox } from 'mapboxgl'; to set up the access token, no popups or controls included!

Then you could separately import JUST the components that you actually use.

These should actually just send events that can be listened and acted upon in your own code that handles the map instance initialisation. The Map should be totally detached from these control components, and maybe give a map instance to methods when needed, but events are much preferable, so mapboxjl.s can be more like a cohesive library instead of mandating framework!

Components should be exported like this: export class AttributionControl { ... }

Currently in addition to Map, I only use these components: AttributionControl, GeolocateControl, Marker, NavigationControl, Popup, Point, ScaleControl.

I have already implemented layer selection and extra info component with Svelte, and that is unnecessarily complicated because the access token can not be passed into Map on initialisation.

The controls styling could be greatly improved and simplified by some skilled frontend developer. I would also rather implement as many controls as possible in Svelte, and just call the necessary mapbox API methods for functionality.

PS. Favouring functional programming instead of OOP would also help.

Kambyses commented 2 years ago

I'd like to add, that problem isn't bundle size per se, it doesn't matter if it's gzipped or not, if you're using cdn etc. The problem is script parsing time and it's really huge and i do wonder if it could be improved. My Lighthouse test claims that about 80% of the script parsing/evaluation goes into mapbox-gl.js while about 50% of bytes of the mapbox-gl.js are unused.

quickshiftin commented 2 years ago

I can concur with @Kambyses, Lighthouse shows 458.5K of 824.1K unused; that's 44%. Seems like there could be some opportunity for code splitting here, despite the complexity of the project.

njradford commented 1 year ago

100% agree with peterhil's comment

samclaus commented 1 year ago

@peterhil (and anyone else who needs a lightweight solution)

I am currently working on Leaflet Lite. The goal is to be a much lighter version of Leaflet that satisfies most basic use cases where people just want a tile layer, some markers, and some vector interaction.

I've already converted the whole Leaflet code base to TypeScript and stripped out some features that didn't seem very critical for most people. I'm brand new to GIS so any help with understanding how the tile/vector layers and animations work under the hood is greatly appreciated.

I extracted map "handlers" out to separate modules that applications must explicitly import (as opposed to passing Boolean options when creating a map) so that more stuff is tree-shakeable.

A lot more work needs to be done and I am actively working on learning and developing the library, but any insights from knowledgeable GIS programmers would speed things up considerably.

ShafSpecs commented 7 months ago

Quoting @peterhil:

This issue should absolutely be reopened, and you definitely can make the library footprint smaller by using named exports.

Definitely, I am surprised there is no ESM available for mapbox. Just providing named exports provides the ability to treeshake using tools like Vite and Webpack.

Like many others in this thread, I am using mapbox for a few things. Placing markers, rotating, panning and layers (drawing lines with geojson source) and my mapbox bundle size is 1.2mb! In an app that has a total size of 2.7MB. And this is after splitting with esbuild.

image I'd like to add that it was originally 2.1MB till I deleted everything in node_modules/mapbox_gl except the main .js and .css file

The controls styling could be greatly improved and simplified by some skilled frontend developer. I would also rather implement as many controls as possible in Svelte, and just call the necessary mapbox API methods for functionality.

This tbh. All the times I use mapbox, I have always had to dig into mapbox to get the functionality for various controls and build my own components on top of the underlying APIs, as the current UI is not easily extensible and doesn't really fit the constraints of the project. Utilising ESM and named exports here would help greatly as it would be easy to create sub-modules for this kind of things

import { NavigationControl } from 'mapbox-gl/navigation'

PS. Favouring functional programming instead of OOP would also help.

Using classes to handle the various aspects of mapbox has introduced unnecessary overhead imo as features get clumped together, both used and unused.

cc @mourner considering this has been an issue for 6 years and it is an issue that seems to plague many mapbox projects, I would highly advise re-opening this issue and mapbox team making this a priority for mapbox-gl in the near future. A lot of solutions for bundle management have sprung up in years (including the wider adoption of ESM) and a few users here have given possible solutions to fix this problems. Thank you

marcfalk commented 7 months ago

+1 for re-opening this issue and making the code easier for bundlers to code split 🕺

gsl-hamzaelhadi commented 7 months ago

+1 for re-opening

navidemad commented 6 months ago

+1 for re-opening this package is awesome but it will be awesome to have a ESM Modules, so esbuild could chunk it

netlas commented 6 months ago

+1 for re-opening. It's a shame... You have such a nice developing tool, having a blast to develop in it. But when its time for depolyment you get a real sad face.

nicolaric commented 5 months ago

+1 please reopen! 🙏 it's by far the biggest chunk in our app.

the bundle size also increased significantly recently (https://github.com/mapbox/mapbox-gl-js/issues/12995).

LuBreGit commented 4 months ago

Jsut to let you know, if you use an older mapbox-gl.js version you can still use it and save some space. I saved it locally and it's 800 KB (latest version is 1.200 KB). It's basically 50% smaller. I love MapBox but 1.200 KB for the map alone is insane, moreso if you just use it for basic stuff like adding a few markers and nothing else.

Ojay commented 3 months ago

Without doubt, +1 for re-opening. It's a fantastic tool and great library but it's hard to justify in production because of the weight.

therealtgd commented 1 month ago

+1 for re-opening.

Shyrogan commented 3 weeks ago

+1 for re-opening

jgauna commented 1 week ago

+1 for re-opening