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
The dev server resolves a request by draining the whole getEntries() iterable and then picking the one entry whose path matches the URL (loadEntriesList() in packages/static/src/rsc/entry.tsx, used by both serveHTML and the HMR path of serveRSC). The cost of serving one page is therefore the cost of enumerating the entire site.
#180 caches the fs-routes enumeration per entries-module instance, which removes the per-request cost — but the initial enumeration cost remains: after server start, and again after every edit to a routed file (which invalidates the entries module), the next request runs every dynamic route's generateStaticParams() before it can render anything. For a large site backed by a CMS or filesystem scan, that is a long stall on the request that should feel like a quick dev reload.
Scope
Both plugin modes are affected, and both should be in scope:
fs-routes mode (createFsRoutesEntries): the enumeration runs generateStaticParams() for every dynamic route and registers a soft-navigation chunk per Server Component node × params combination — all to serve one page.
plain entries.tsx mode (entries option): the user's own getEntries() generator is drained fully per request. User generators can be arbitrarily expensive (fetching data per entry), and nothing caches them — the fs-routes cache in fix: cache fs-routes enumeration across dev requests #180 lives inside the fs-routes runtime, not in the dev server.
Direction (sketch)
Serve a request by resolving only the entry that matches the URL:
Extend the entries contract with an optional lookup capability (e.g. a getEntryForPath(urlPath) alongside the iterable, or an object form of the default export), falling back to full iteration when absent. The build keeps using full iteration.
For fs-routes, match the URL against the route tree first, then run only the matching route chain's generateStaticParams() to validate the params and build the page — instead of expanding every route upfront.
Soft-navigation chunks are the hard part: a page's slot chunks map today bakes in the IDs of every sibling params combination, which requires knowing all combos for the nodes on the page. Options include rendering chunks on demand in dev (derive the chunk from a stable ID encoding node + params at fetch time, rather than pre-registering everything) or enumerating combos only for the routes the requested page actually renders through.
Site-wide validations that currently piggyback on full enumeration (URL collisions across routes, generateStaticParams value validation) would need to stay build-time checks, with dev validating lazily per request.
Non-goals
Build behavior: a static build must still enumerate every page.
Background
The dev server resolves a request by draining the whole
getEntries()iterable and then picking the one entry whose path matches the URL (loadEntriesList()inpackages/static/src/rsc/entry.tsx, used by bothserveHTMLand the HMR path ofserveRSC). The cost of serving one page is therefore the cost of enumerating the entire site.#180 caches the fs-routes enumeration per entries-module instance, which removes the per-request cost — but the initial enumeration cost remains: after server start, and again after every edit to a routed file (which invalidates the entries module), the next request runs every dynamic route's
generateStaticParams()before it can render anything. For a large site backed by a CMS or filesystem scan, that is a long stall on the request that should feel like a quick dev reload.Scope
Both plugin modes are affected, and both should be in scope:
createFsRoutesEntries): the enumeration runsgenerateStaticParams()for every dynamic route and registers a soft-navigation chunk per Server Component node × params combination — all to serve one page.entries.tsxmode (entriesoption): the user's owngetEntries()generator is drained fully per request. User generators can be arbitrarily expensive (fetching data per entry), and nothing caches them — the fs-routes cache in fix: cache fs-routes enumeration across dev requests #180 lives inside the fs-routes runtime, not in the dev server.Direction (sketch)
Serve a request by resolving only the entry that matches the URL:
getEntryForPath(urlPath)alongside the iterable, or an object form of the default export), falling back to full iteration when absent. The build keeps using full iteration.generateStaticParams()to validate the params and build the page — instead of expanding every route upfront.chunksmap today bakes in the IDs of every sibling params combination, which requires knowing all combos for the nodes on the page. Options include rendering chunks on demand in dev (derive the chunk from a stable ID encoding node + params at fetch time, rather than pre-registering everything) or enumerating combos only for the routes the requested page actually renders through.generateStaticParamsvalue validation) would need to stay build-time checks, with dev validating lazily per request.Non-goals