Conversation
…b URL maplibre-gl 6 locates its worker via `import.meta.url`, which bundlers can't reliably follow for a dependency: webpack ignores it, and Vite copies the `.mjs` worker verbatim so stock servers reject it as a module worker and its content-hashed `maplibre-gl-shared` sibling can't be found. Tiles then silently fail to render. A Vite plugin now serves `virtual:maplibre-worker-source`: the installed maplibre-gl worker bundled into a self-contained script and exported as a string, emitted next to `map.js` in `dist`. `LeafletMap` starts the worker from a Blob URL of it unless the consumer set a worker URL themselves, so no bundler configuration is needed. The plugin asserts the worker's top-level registration survived bundling so an empty tree-shaken worker can't ship, and the build cache key now includes `package.json`. `maplibre-gl` is now a `^6.7.0` range. Since the worker is frozen at build time while the main-thread maplibre-gl resolves at install time, `LeafletMap` warns when the two versions differ, so a protocol mismatch is no longer a silent failure. Co-Authored-By: Claude Fable 5.1 <[email protected]>
Drops the `?maplibreWorkerAsset` asset rule and maps `virtual:maplibre-worker-source` to the built copy in `packages/ts/dist`, since webpack treats `virtual:` as a URL scheme and can't alias it. Co-Authored-By: Claude Fable 5.1 <[email protected]>
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Contributor
Author
|
@lee00678 I've not tested it properly yet on my end. The MapLibre update was kind of a breaking change so it would be nice to fix and publish as 1.7.1 |
Collaborator
|
I was just about to ask if you've tested this on your end. Because we don't have a good source of verification other than what we use here and the dev examples we have. |
Collaborator
|
@rokotyan I think this looks good, we plan on release 1.7.1 tmw. Flag me if you want us to hold off. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #921
With maplibre-gl 6,
LeafletMap's MapLibre renderer silently renders no tiles in apps without maplibre-specific bundler config. This makes the published@unovis/tswork with zero consumer configuration, and removes the?maplibreWorkerAssetmarker and the dev-gallery webpack rules that supported it.What changed
packages/ts/vite-plugin-maplibre-worker-source.tsserves a virtual module: the installedmaplibre-gl/dist/maplibre-gl-worker.mjsbundled into one self-contained IIFE (via Vite'sbuild()API, the worker file as entry) and exported as a string, plus the maplibre version it was built from. It's emitted asdist/components/leaflet-map/modules/maplibre-worker-source.js, so consumers get an ordinary ES module.map.tsimports it lazily in the MapLibre branch and callssetWorkerUrl(URL.createObjectURL(new Blob([source], { type: 'text/javascript' }))). Theif (!maplibre.getWorkerUrl())guard is kept, so a consumer's ownsetWorkerUrl()still wins. The Blob URL is created once and never revoked: maplibre re-reads the URL for every worker in its pool and again when the pool is rebuilt.self.worker = new Worker(self)registration is missing, if the chunk still imports anything, or if it usesimport.meta. maplibre marks its dist as side-effect free, so a tree-shaken empty worker otherwise builds "successfully".LeafletMapwarns whenmaplibre.getVersion()differs from the version the worker was built from, so a main-thread/worker mismatch is no longer silent.packages/ts/srcwith webpack, which can't resolve a Vite virtual module and treatsvirtual:as a URL scheme (soresolve.aliasdoesn't apply). ANormalModuleReplacementPluginmaps the id to the built file inpackages/ts/dist. Themaplibre-gl.mjsparser rule stays: without it webpack's "Critical dependency" warning returns.Why this design
Alternatives and why they were rejected are in #921. In short: Vite's
?worker&urlhas the sameimport.meta.urlfailure modes;?worker&inlineexports only a Worker factory and revokes its Blob URL on start, while maplibre's only hook issetWorkerUrl(string); a postinstall build is skipped by pnpm 10 and--ignore-scripts; a CDN worker URL adds a third-party runtime dependency.CSP
Consumers rendering the MapLibre renderer need
worker-src 'self' blob:. maplibre itself already uses Blob workers for cross-origin URLs. The CSP guide now says so. (Side note: the guide previously claimed the ELK graph spawns a Blob worker;elk.bundled.jsruns its layout in-thread via a fake worker, so that directive was never needed there. Happy to correct that in this PR or separately.)Verification
Throwaway Vite app consuming the packed
distvia afile:tarball, with no maplibre-specific config:vite build, served by a static server mimicking deployed nginx (default_type application/octet-stream, stockmime.types, SPA fallback)blob:. Only.jsassets requested; no.mjs, nomaplibre-gl-shared*, no failed requests, no console errors.vite devwith default dependency pre-bundlingnode_modules/.vite/deps/.maplibregl.setWorkerUrl('/custom-worker.js')before the map mountspnpm dev, webpack) Vector Map exampleAlso:
pnpm build(core),pnpm build:dev, lint and type-check clean for the touched files. A secondpnpm buildis skipped by the.srcshacache, whose key now includespackage.json.Consumer cleanup this unblocks
Apps that worked around this can delete: their
?worker&urlbundle ofmaplibre-gl-worker.mjsand thesetWorkerUrl()call that used it, a directmaplibre-gldependency added only for that, and any Viteexternal/entryFileNamestweaks that kept the worker unhashed. Bundler asset rules emittingmaplibre-gl-{worker,shared}.mjscan go too.Open question for maintainers
maplibre-glis declared as^6.7.0here. Since the worker is frozen at publish time while the main-thread maplibre-gl resolves at the consumer's install time, an exact pin would make the two match by construction (package managers nest a matching copy for us). The runtime warning covers the mismatch either way; pinning exactly is a one-line change if you prefer it.🤖 Generated with Claude Code