Bundle the MapLibre worker with Vite - #167
Conversation
MapLibre 6 resolves its worker next to the bundled library chunk by default. That file is not emitted by Vite, so production receives the SPA HTML fallback instead and vector maps never finish loading. Import the worker through Vite's worker pipeline and configure its generated URL before creating the map. Signed-off-by: Yura Gubkin <uagubkin@gmail.com>
biodranik
left a comment
There was a problem hiding this comment.
The diagnosis and the fix both hold up — I reproduced the bug and the repair in a real browser rather than by reading.
On main, the built page requests /assets/maplibre-gl-worker.mjs and gets 404; with this branch it gets 200 and the dispatcher comes up with a live actor. The cause is exactly as described: defaultWorkerUrl() in 6.4.1 is new URL('./maplibre-gl-worker.mjs', import.meta.url), which Rollup does not statically analyse, so the file is never emitted. setWorkerUrl is also the only override v6 still exposes — workerClass is gone — so there is no neater hook to reach for. tsc -b and vite build pass.
One thing to note but not act on: the emitted worker is 469 kB raw / 131 kB gzipped, because Vite inlines maplibre-gl-shared into it while the main chunk keeps its own copy. That duplication is unavoidable — a worker has its own module graph — and it only loads for people who render a map, i.e. everyone here.
One follow-up, outside the diff: optimizeDeps.exclude: ['maplibre-gl'] in vite.config.ts (added in 43c0c49, "Fix maplibre-gl v6 build") becomes dead config once this lands, and I would drop it in the same PR.
It exists only as a dev-side workaround for this same root cause: with it removed on main, the dev server requests /node_modules/.vite/deps/maplibre-gl-worker.mjs → 404, because pre-bundling moves the module and import.meta.url follows it. Excluding maplibre kept it at its real path so the relative guess still landed. Once setWorkerUrl is set the default resolution is never consulted, so the exclusion has nothing left to protect.
Verified on this branch with the exclusion removed: dev serves the worker (200, one actor) with maplibre pre-bundled again — fewer dev requests and a faster cold start — and the production build is byte-identical, same asset hashes, since optimizeDeps is dev-only. Removing it also spares the next reader a piece of unexplained config whose reason will have evaporated.
Generated by Claude Code
biodranik
left a comment
There was a problem hiding this comment.
Thanks for the fix! Claude is nitpicking, need to tame it.
MapLibre 6 resolves its worker next to the bundled library chunk by default. That file is not emitted by Vite, so production receives the SPA HTML fallback instead and vector maps never finish loading.
Import the worker through Vite's worker pipeline and configure its generated URL before creating the map.