Start: generated preloads should default to fetchpriority="low", with production before/after data #8547
quanglam2807
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
TL;DR: Start fetches every generated route preload at
Highpriority, where it competes with the stylesheet, font and LCP image, even on server-rendered pages that don't need that JS to paint. We shippedfetchpriority="low"on those preloads on two production sites. Mobile FCP dropped from 5.5–6.9 s to 3.1–3.5 s on every page we measured, and desktop FCP from 1.3–2.6 s to 0.6–0.8 s, with no measurable cost to hydration or click latency. React and Next.js already do this for their own bootstrap scripts. I think it should be Start's default: tracked in #8546, implemented in draft PR #8212.Production before/after
webcatalog.io: Start 1.168, React 19.3, Vite 8, 71–79 preloads per page (about 445 KB of JS). The only change was
fetchpriority="low"on the generated preloads. Lighthouse 13.5 medians:A second production site, lexibird.com (same stack, 43 preloads), with the same change, 5 runs each:
TBT, TTI and hydration are unchanged within noise on both sites, and neither site showed hydration errors in production.
Isn't this just Lighthouse?
No. Lighthouse's simulation does exaggerate priority effects (see @TiagoGranelli's explanation in #8212), so we also measured real Chrome under applied throttling, 5 interleaved runs:
High)fetchpriority="low"Hydration doesn't move: the connection is the bottleneck, so the last chunk arrives at the same time;
lowjust lets CSS, font and images go first. Full methodology: #8212 (comment)Why default, not opt-in
fetchPriority: 'low', and Next.js inherits that. Start is the outlier.Where it shouldn't apply
ssr: falsematches and SPA mode: the JS is the content, so keep today's priority. Start knows which matches were server-rendered, so the default can be scoped to them.HeadContentprop ortransformAssetsfield), not against the default.fetchPriority, or the HTML attribute arrives too late wherever hints are sent.Try it today
useTagsandAssetare exported from@tanstack/react-router, so you can render your ownHeadContentthat addsfetchPriority: 'low'tolink[rel=modulepreload]tags. That's how the production numbers above were produced.If you run a Start app, especially one with a large preload set, please share your before/after numbers, ideally field data (CrUX or RUM) for FCP, LCP and INP. And if you have a case where
lowmakes things worse, that's exactly what's needed to get the default right.Related: #8546 (issue), #8212 (draft PR), #6749, #8511.
Edited 2026-09-28: added lexibird.com as a second production site; added production before/after data, and changed the proposal from an opt-in to a default (scoped to server-rendered matches) with an escape hatch.
All reactions