You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Round 2 of the eager-main.js diet.#4395 was closed by #4403, but #4403 only did round 1 — it deferred the search palette + Sentry init policy (~80 KB raw / ~15 KB br off main.js). That's ~4% of the eager JS. The score-moving bulk is still eager and untracked; this issue tracks it.
Current state (measured on prod after #4403, 2026-06-24)
Cold mobile (fresh Chrome, Slow 4G + 4× CPU, median of 3): FCP/LCP ~872 ms, CLS 0.007, TBT ~705 ms, DCL ~6.3 s.
Delivery is solved (Brotli). The remaining bottleneck is JS parse/execute — TBT ~700 ms and DCL ~6.3 s are dominated by eager JS that compression doesn't help.
The targets (still eagerly modulepreload-ed, by raw size on prod)
Chunk
Raw
Notes
data-freshness
357 KB
single fattest eager satellite
gdelt-intel
190 KB
cached-risk-scores
121 KB
panel-storage
112 KB
≈ 780 KB raw eager — ~10× what #4403 moved. All four land in the same ~865 ms wave as main.js and feed the ~700 ms TBT.
Approach
Defer each behind a dynamic import() on the same pattern #4403 / #4386 (settings/checkout) / #4390 (map) already use. For each:
Audit what drags it onto the eager path — trace the static import chain from the main entry (and the modulepreload list / LAZY_HTML_PRELOAD_CHUNKS in vite.config.ts).
Confirm it is NOT first-paint-critical before deferring. Some may genuinely be needed early (e.g. if data-freshness drives an above-the-fold freshness indicator). Don't trade a TBT win for a visible-content regression — same discipline as the CSS-import-removal reviews. Where a piece is needed early, split the first-paint-critical slice from the deferrable bulk.
Verified by a median-of-≥3 cold mobile run (single throttled samples are too noisy — TBT varies hundreds of ms run-to-run) plus the deterministic bundle-size delta.
Round 2 of the eager-
main.jsdiet. #4395 was closed by #4403, but #4403 only did round 1 — it deferred the search palette + Sentry init policy (~80 KB raw / ~15 KB br offmain.js). That's ~4% of the eager JS. The score-moving bulk is still eager and untracked; this issue tracks it.Current state (measured on prod after #4403, 2026-06-24)
main-BX3KB0N8.js: 1,012 KB raw / 287 KB br (was 1,091 / 306 pre-perf(startup): lazy-load dashboard search #4403).The targets (still eagerly
modulepreload-ed, by raw size on prod)data-freshnessgdelt-intelcached-risk-scorespanel-storage≈ 780 KB raw eager — ~10× what #4403 moved. All four land in the same ~865 ms wave as
main.jsand feed the ~700 ms TBT.Approach
Defer each behind a dynamic
import()on the same pattern #4403 / #4386 (settings/checkout) / #4390 (map) already use. For each:modulepreloadlist /LAZY_HTML_PRELOAD_CHUNKSinvite.config.ts).data-freshnessdrives an above-the-fold freshness indicator). Don't trade a TBT win for a visible-content regression — same discipline as the CSS-import-removal reviews. Where a piece is needed early, split the first-paint-critical slice from the deferrable bulk.latestSearchAdsb/latestTechEventspattern from perf(startup): lazy-load dashboard search #4403).Acceptance
main.jstransfer and itsunused-javascriptbytes.Refs
#4395 (closed, round 1 = #4403), #4379/#4386 (prior diet), #3987 (homepage LCP→<3s / Lighthouse→90 tracker), #4335 (split/stage initial JS).
https://claude.ai/code/session_015Ae5Xavw1ZV4GMCWEsgKwe