Lazy-load MapboxMap child components - #566
Conversation
Register MapboxMap's children with dynamic-import loaders instead of static imports, so each child's code is code-split and fetched only when a matching element exists on the page — the map no longer drags the whole family (~22 KB of wrapper code) into its chunk. mapbox-gl is loaded by MapboxMap regardless and is unaffected. - resolveWhenMapboxMapIsLoaded now accepts a loader factory (or a class, for backward compatibility) and awaits the dynamic import after the map has loaded. - Harden StoreLocator's cluster wiring for the resulting network-delayed child mount: replace the microtask-bound poll with the map's `sourcedata` signal plus a real-time retry (250ms x 20 ~= 5s), both torn down once wiring settles or on destroy. Browser verification of the StoreLocator timing under real network latency is a follow-up (jsdom can't reproduce it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NeZwHwo3d9rYsCxJUQqTep
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #566 +/- ##
============================================
- Coverage 86.19% 86.07% -0.13%
Complexity 145 145
============================================
Files 139 139
Lines 4354 4401 +47
Branches 817 824 +7
============================================
+ Hits 3753 3788 +35
- Misses 528 539 +11
- Partials 73 74 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Code ReviewRisk: Low — no blocking issues; safe to merge aside from nits. This MR lazy-loads Review usage: 299,785 in (242,688 cached) / 8,192 out tokens — $0.3263 (cloudflare-ai-gateway/gpt-5.4, thinking: medium) Reviewed by @weareikko/code-review v0.9.4 for commit e4003b3. Previous review runsPrevious run archived 2026-08-01T11:10:48ZCode ReviewRisk: Low — No blocking issues found in the lazy-loading and This MR replaces Review usage: 163,053 in (129,536 cached) / 6,917 out tokens — $0.2199 (cloudflare-ai-gateway/gpt-5.4, thinking: medium) Reviewed by @weareikko/code-review v0.9.4 for commit ace367b. |
Export Size@studiometa/ui
Unchanged@studiometa/ui
|
The child components each have a default export, and js-toolkit's resolver
unwraps `module.default`, so the `.then((m) => m.X)` in the lazy loaders is
redundant. Register each child as `() => import('./X.js')`.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NeZwHwo3d9rYsCxJUQqTep
The 0.3.11 release fixes the multi-chunk dependency-emit collision (studiometa/playground#73) that broke docs_build with: Conflict: Multiple assets emit different content to the same filename static/deps/@studiometa/ui-mapbox/index.js Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NeZwHwo3d9rYsCxJUQqTep
|
The The build was failing at webpack seal time with: Root cause was in Fixed upstream in studiometa/playground#73 (merged), released as This branch now pins
|
|
Superseded by #567, which re-architects the whole |
Follow-up optimization for
@studiometa/ui-mapbox.📚 Description
MapboxMapstatically imported all 11 children (markers, popups, controls, source, layer, images, cluster), so importing the map dragged the whole family's wrapper code into its chunk even for a page that only uses, say, a marker. This registers each child with a dynamic-import loader instead, so js-toolkit fetches a child's code only when a matching element exists on the page.resolveWhenMapboxMapIsLoadednow accepts a loader factory() => import(...)(or a class, for backward-compat) and awaits the dynamic import after the map'sload.config.componentsentry is nowresolveWhenMapboxMapIsLoaded(() => import('./X.js').then((m) => m.X)).⚖️ Honest impact
This is a pay-per-use win on the child wrapper code, not the heavyweight:
mapbox-gl(~230 kB) is loaded byMapboxMapregardless — unaffected.@mapbox/mapbox-gl-geocoderpeer was already lazy (dynamic import insideMapboxGeocoder).mapbox-glexternal): a "MapboxMap + one marker" page goes from an 11.4 kB up-front child chunk to ~2.5 kB (entry + the marker chunk), with the cluster (~4 kB min), geocoder, controls, etc. never fetched. Total across all chunks grows slightly from split boilerplate — paid only by a page using every child.🔧 StoreLocator hardening (required)
With lazy children, the cluster mounts only after its chunk is network-fetched, which outlasts StoreLocator's old microtask-bound wiring poll. The poll is replaced with the map's
sourcedatasignal (fires when the cluster adds its source, at any latency) plus a real-time retry (~5 s budget), both torn down once wiring settles or on destroy.✅ Verification
Build, lint,
npm run test(689 pass incl. a new resolver spec) all pass. Real-browser verification of the StoreLocator timing under network-latency chunk loading is being done via the playground stories (jsdom can't reproduce it) — results to follow on this PR.❓ Type of change
🤖 Generated with Claude Code