next.js
d18f7aee - [Bug Demo] Static generation runs on every request for routes with `unstable_instant = false` at the root

Commit
40 days ago
[Bug Demo] Static generation runs on every request for routes with `unstable_instant = false` at the root This is a demonstration of a bug, not a fix. The debug logs added here are intentional and meant to illustrate the issue. When a route has `unstable_instant = false` at the root segment (i.e. `connection()` called outside a Suspense boundary), the route is marked as Dynamic in the build output. At runtime with Cache Components enabled, `prerenderToStream` and `collectSegmentData` run on every single request instead of caching the static generation result. In contrast, when the same `connection()` call is wrapped in a Suspense boundary — either with a real fallback (partial prerender) or with a null fallback (the old "suspense around body" pattern) — neither function runs at runtime. The static generation result is served from cache as expected. I haven't thought of a way to write a regression test for this that doesn't rely on implementation details. Logging inside a component would get de-duped by the memory cache anyway. I've demonstrated by adding logs to Next.js itself for now. Steps to reproduce: cd test/e2e/app-dir/segment-cache/bug-dynamic-prerender-per-request pnpm next build pnpm next start # In another terminal: curl http://localhost:3000/with-suspense curl http://localhost:3000/suspense-around-body curl http://localhost:3000/without-suspense The build output shows /without-suspense as fully dynamic: Route (app) ┌ ○ / ├ ○ /_not-found ├ ◐ /suspense-around-body ├ ◐ /with-suspense └ ƒ /without-suspense ○ (Static) prerendered as static content ◐ (Partial Prerender) prerendered as static HTML with dynamic server-streamed content ƒ (Dynamic) server-rendered on demand Note that /without-suspense is marked as ƒ (Dynamic) rather than ◐ (Partial Prerender). The fact that /suspense-around-body — which also has no meaningful static HTML shell — is marked as ◐ is highly suggestive that unstable_instant = false should be treated the same way. At minimum, the inconsistency between these two routes is wrong. Expected: No runtime logs for any route. Static generation results should be cached and served without re-running the prerender path on each request. Actual: The /without-suspense request produces these logs on the server: [prerenderToStream] route: /without-suspense | isBuildTimePrerendering: undefined [collectSegmentData] route: /without-suspense | isBuildTimePrerendering: undefined The /with-suspense and /suspense-around-body requests produce no logs (correct).
Author
Parents
Loading