Skip to content

perf(frontend): load the map tiles without waiting for the overlay and dialogs - #613

Merged
JuliusHenke merged 1 commit into
masterfrom
perf/frontend-independent-suspense-boundaries
Oct 12, 2026
Merged

JuliusHenke merged 1 commit into
masterfrom
perf/frontend-independent-suspense-boundaries

Conversation

@JuliusHenke

Copy link
Copy Markdown
Member

What

A Lighthouse run showed that the LCP element (a map tile) was requested about 500 ms after the map chunk had arrived. In App.tsx the map, the overlay and the attribution links shared one <Suspense> boundary, and React only commits a boundary once every lazy child is ready. The tiles therefore waited for the date picker (233 kB), the icons chunk (102 kB) and a 125 ms render task. The day data request, which starts in the map's effect, waited as well.

  • The map is now part of the entry (it is always needed on first paint), so its chunk is preloaded in parallel with the entry script instead of being requested after it.
  • The overlay has its own Suspense boundary (no fallback), so the map no longer waits for it.
  • ExternalLink is imported directly. It was lazy-imported in App.tsx but statically imported by five other modules, so the lazy import only delayed the boundary (Vite warned INEFFECTIVE_DYNAMIC_IMPORT).
  • The relay details and family dialogs are loaded when they are opened for the first time (they stay mounted afterwards, so they close with their transition). That removes three requests from the startup.
  • ResponsiveRelayDetailsDialog derived its state from changes of the relays and started with the current value, so a dialog that mounts when it is opened missed the first location. Its tracking state now starts empty. The existing marker click test caught this.

Measurement

Same build settings and a deterministic local mock API (6,900 relays per day, 25 ms latency), Lighthouse 13.4.1, simulated throttling (mobile and desktop presets), median of 5 runs:

LCP before LCP after Perf score before -> after Tile load delay
Desktop 1390 ms 995 ms (-28%) 96 -> 99 391 -> 66 ms
Mobile 6230 ms 4476 ms (-28%) 74 -> 80 98 -> 66 ms*

* The mobile preset's raw "load delay" was already small there, the gain shows in the LCP itself.

Other numbers (median): requests 62 -> 52 (desktop), transfer 779 -> 551 KiB, mobile TBT 54 -> 6 ms, CLS 0. FCP is unchanged on desktop (567 -> 570 ms) and slightly higher on mobile (2.57 -> 2.73 s), since the map is now part of the entry graph. Real tiles from the CARTO CDN were used, so a few percent of run-to-run noise is expected.

Verification

tsc, eslint, vite build (the warning is gone) and yarn test:run (275 tests) pass. The Lighthouse tool was installed in a scratch directory only (lighthouse@13.4.1: Apache-2.0, 2.5 months old, no advisories on deps.dev, no OpenSourceMalware report; transitive dependencies are not covered by those checks), nothing was added to the project.

Dependencies / deployment

None.

🤖 Generated with Claude Code

…d dialogs

The map, the overlay and the attribution shared one Suspense boundary, so no tile was requested before the date picker and icon chunks were loaded and rendered (about 500 ms of the LCP). The map is now part of the entry, the overlay has its own boundary, and the relay and family dialogs are only loaded when they are opened for the first time.

Lighthouse (local build, mock API, median of 5): LCP desktop 1390 -> 995 ms, mobile 6230 -> 4476 ms.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@JuliusHenke JuliusHenke added enhancement New feature or request frontend labels Oct 12, 2026
@github-actions

Copy link
Copy Markdown

Visit the preview URL for this PR (updated for commit 11cfb6f):

https://tormap-36f44--pr613-perf-frontend-indepe-f3t0zrlp.web.app

(expires Wed, 11 Nov 2026 20:51:36 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: 0c1f71965de18e60b0e686b0d0356977fec090dc

@JuliusHenke
JuliusHenke marked this pull request as ready for review October 12, 2026 21:15
@JuliusHenke
JuliusHenke merged commit 2292034 into master Oct 12, 2026
14 of 15 checks passed
@JuliusHenke
JuliusHenke deleted the perf/frontend-independent-suspense-boundaries branch October 12, 2026 21:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request frontend

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant