[PR #553] [MERGED] feat: production prerender pipeline #670

Closed
opened 2026-05-06 13:09:27 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/553
Author: @james-elicx
Created: 3/15/2026
Status: Merged
Merged: 3/16/2026
Merged by: @james-elicx

Base: mainHead: feat/prod-prerender-pipeline


📝 Commits (10+)

  • e550825 feat: production prerender pipeline (no dev server)
  • b9015f0 chore: merge main (vite-plus migration) and fix createIsolatedFixture filter param type
  • 61236f1 fix: build Pages Router SSR bundle for hybrid app+pages projects
  • 18fde83 Clean up run-prerender: remove deprecated shim, fix progress arithmetic and typos
  • a0b4bdf regen snaps
  • 1edf2ee refactor: clean up prerender pipeline, cache shim, and report utilities
  • 088d522 fix: remove unused appDir from PrerenderAppOptions and all callers
  • add5e0f refactor: miscellaneous cleanups across prerender, cache, cli, and deploy
  • 0ce0936 refactor: document gaps, re-detect project after installDeps, fix Vite resolution in deploy.ts
  • 8dd588d refactor(prerender): unify onProgress to single call site; document pageCount semantics

📊 Changes

49 files changed (+3814 additions, -948 deletions)

View changed files

📝 examples/app-router-cloudflare/app/blog/[slug]/page.tsx (+4 -0)
📝 examples/app-router-cloudflare/package.json (+1 -0)
📝 packages/vinext/package.json (+7 -2)
packages/vinext/src/build/prerender.ts (+1275 -0)
📝 packages/vinext/src/build/report.ts (+53 -8)
packages/vinext/src/build/run-prerender.ts (+321 -0)
📝 packages/vinext/src/build/static-export.ts (+55 -673)
📝 packages/vinext/src/cli.ts (+107 -5)
📝 packages/vinext/src/deploy.ts (+86 -40)
📝 packages/vinext/src/entries/app-rsc-entry.ts (+129 -0)
📝 packages/vinext/src/entries/app-ssr-entry.ts (+17 -2)
📝 packages/vinext/src/entries/pages-server-entry.ts (+2 -2)
📝 packages/vinext/src/index.ts (+47 -8)
📝 packages/vinext/src/server/prod-server.ts (+39 -8)
📝 packages/vinext/src/shims/cache.ts (+85 -49)
📝 pnpm-lock.yaml (+94 -31)
📝 pnpm-workspace.yaml (+4 -1)
📝 tests/__snapshots__/entry-templates.test.ts.snap (+279 -2)
📝 tests/app-router.test.ts (+16 -42)
📝 tests/build-report.test.ts (+2 -3)

...and 29 more files

📄 Description

Summary

  • Adds `prerenderPages()` and `prerenderApp()` in `build/prerender.ts` — render all static/ISR routes using production bundles only, no `ViteDevServer` dependency at prerender time
  • `runPrerender()` in `build/run-prerender.ts` consolidates route scanning, progress reporting, and manifest writing for both App and Pages Router (hybrid projects included); the old `runPrerenderWithDevServer()` shim is removed
  • `static-export.ts` becomes a thin adapter — all rendering logic lives in the prerender layer
  • Prerendered HTML/RSC output for non-export builds goes to `dist/server/prerendered-routes/` instead of `dist/client/`. On Cloudflare Workers, `not_found_handling: "none"` means every request hits the worker first so files in `dist/client/` are never auto-served for page requests — they were uploaded but inert. Keeping prerendered output out of `dist/client/` also prevents a future issue where KV pre-population would cause ISR routes to be served as stale static files forever. `output: 'export'` builds are unaffected (still write to `dist/client/`)
  • `prod-server.ts` now serves prerendered `.html` files for extension-less paths (e.g. `/about` → `about.html`)
  • `NoOpCacheHandler` added to `shims/cache.ts` to skip wasteful ISR writes during prerender; `CacheHandler` is save/restored around prerender calls for isolation
  • Build report integrates `PrerenderResult` — routes confirmed static by speculative render are upgraded from `unknown` → `static` in the output
  • Hybrid projects (both `app/` and `pages/`): after the App Router multi-env build, a separate SSR-only build produces the Pages Router bundle so the prerender phase finds both bundles
  • Adds `rscOutDir` / `ssrOutDir` / `clientOutDir` / `disableAppRouter` options to `VinextOptions` so tests can build multiple fixtures in parallel into isolated output directories
  • Miscellaneous cleanups: extract `loadBundle()`, rename `isExplicitlyDynamic` → `isConfiguredDynamic`, `SetCtx` interface, `CacheResultWrapper`, fix single-row table corner, unify `onProgress` to single call site, remove unused `appDir` from `PrerenderAppOptions`
  • Support for pre-rendering workers builds via Wrangler servers.

Tests

  • 36 new tests in `tests/prerender.test.ts` covering `prerenderPages`, `prerenderApp`, hybrid, and export wiring
  • All suites pass: 265 app-router + 172 pages-router + 36 prerender + 14 static-export = 487 tests
  • Typecheck, lint, and fmt all clean

Future tasks

  • Serving pre-rendered responses from memory cache.
  • Populating remote cache during deployment.
  • Configurable concurrency for pre-render pipeline.
  • Dedupe RSC requests during pre-render and extract RSC payload from HTML response.
  • Improve progress bar tracking for the pre-render phase to be a better reflection of the work that is happening.
  • Expose a better public API for manual external control over pre-rendering and static exports.
  • Improve static analysis detection classification for routes when not going through the pre-render pipeline.
  • Lightweight worker and auto-config options for static exports.
  • Wire up new static export fixture to actual tests and deployments once static export functionality is finished.
  • Provide some information in the route report about what was pre-rendered.
  • Turn on pre-rendering + KV population for the deployed example apps.
  • Improve pre-rendering test suites.
  • Performance improvements for resolveParentParams lookups.
  • Switch unstable_dev to unstable_startWorker and add more informational logs about the server being started.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/cloudflare/vinext/pull/553 **Author:** [@james-elicx](https://github.com/james-elicx) **Created:** 3/15/2026 **Status:** ✅ Merged **Merged:** 3/16/2026 **Merged by:** [@james-elicx](https://github.com/james-elicx) **Base:** `main` ← **Head:** `feat/prod-prerender-pipeline` --- ### 📝 Commits (10+) - [`e550825`](https://github.com/cloudflare/vinext/commit/e55082599726d97d9bb0b93ab1179a28f138ad50) feat: production prerender pipeline (no dev server) - [`b9015f0`](https://github.com/cloudflare/vinext/commit/b9015f0fd5674984aefcca5f689fe1e165e90409) chore: merge main (vite-plus migration) and fix createIsolatedFixture filter param type - [`61236f1`](https://github.com/cloudflare/vinext/commit/61236f14a823d68b3efb8074dcfb8acc49720b14) fix: build Pages Router SSR bundle for hybrid app+pages projects - [`18fde83`](https://github.com/cloudflare/vinext/commit/18fde834b519354c546e31c946baa6c18a83bbc1) Clean up run-prerender: remove deprecated shim, fix progress arithmetic and typos - [`a0b4bdf`](https://github.com/cloudflare/vinext/commit/a0b4bdfe2de4f31ab2115a8e51f1b387f43793dd) regen snaps - [`1edf2ee`](https://github.com/cloudflare/vinext/commit/1edf2ee7804501c903bb4625f84ea983685c5d74) refactor: clean up prerender pipeline, cache shim, and report utilities - [`088d522`](https://github.com/cloudflare/vinext/commit/088d5229c03568b67619760fa2f47a68da59b54c) fix: remove unused appDir from PrerenderAppOptions and all callers - [`add5e0f`](https://github.com/cloudflare/vinext/commit/add5e0f7a38685cbe78d3f8c241cc995901cf8e3) refactor: miscellaneous cleanups across prerender, cache, cli, and deploy - [`0ce0936`](https://github.com/cloudflare/vinext/commit/0ce0936afcda6594e185993e33c054cc3778f141) refactor: document gaps, re-detect project after installDeps, fix Vite resolution in deploy.ts - [`8dd588d`](https://github.com/cloudflare/vinext/commit/8dd588d55e4206b6f3b78433adfcf3ec2a68cae6) refactor(prerender): unify onProgress to single call site; document pageCount semantics ### 📊 Changes **49 files changed** (+3814 additions, -948 deletions) <details> <summary>View changed files</summary> 📝 `examples/app-router-cloudflare/app/blog/[slug]/page.tsx` (+4 -0) 📝 `examples/app-router-cloudflare/package.json` (+1 -0) 📝 `packages/vinext/package.json` (+7 -2) ➕ `packages/vinext/src/build/prerender.ts` (+1275 -0) 📝 `packages/vinext/src/build/report.ts` (+53 -8) ➕ `packages/vinext/src/build/run-prerender.ts` (+321 -0) 📝 `packages/vinext/src/build/static-export.ts` (+55 -673) 📝 `packages/vinext/src/cli.ts` (+107 -5) 📝 `packages/vinext/src/deploy.ts` (+86 -40) 📝 `packages/vinext/src/entries/app-rsc-entry.ts` (+129 -0) 📝 `packages/vinext/src/entries/app-ssr-entry.ts` (+17 -2) 📝 `packages/vinext/src/entries/pages-server-entry.ts` (+2 -2) 📝 `packages/vinext/src/index.ts` (+47 -8) 📝 `packages/vinext/src/server/prod-server.ts` (+39 -8) 📝 `packages/vinext/src/shims/cache.ts` (+85 -49) 📝 `pnpm-lock.yaml` (+94 -31) 📝 `pnpm-workspace.yaml` (+4 -1) 📝 `tests/__snapshots__/entry-templates.test.ts.snap` (+279 -2) 📝 `tests/app-router.test.ts` (+16 -42) 📝 `tests/build-report.test.ts` (+2 -3) _...and 29 more files_ </details> ### 📄 Description ## Summary - Adds \`prerenderPages()\` and \`prerenderApp()\` in \`build/prerender.ts\` — render all static/ISR routes using **production bundles only**, no \`ViteDevServer\` dependency at prerender time - \`runPrerender()\` in \`build/run-prerender.ts\` consolidates route scanning, progress reporting, and manifest writing for both App and Pages Router (hybrid projects included); the old \`runPrerenderWithDevServer()\` shim is removed - \`static-export.ts\` becomes a thin adapter — all rendering logic lives in the prerender layer - Prerendered HTML/RSC output for non-export builds goes to \`dist/server/prerendered-routes/\` instead of \`dist/client/\`. On Cloudflare Workers, \`not_found_handling: "none"\` means every request hits the worker first so files in \`dist/client/\` are never auto-served for page requests — they were uploaded but inert. Keeping prerendered output out of \`dist/client/\` also prevents a future issue where KV pre-population would cause ISR routes to be served as stale static files forever. \`output: 'export'\` builds are unaffected (still write to \`dist/client/\`) - \`prod-server.ts\` now serves prerendered \`.html\` files for extension-less paths (e.g. \`/about\` → \`about.html\`) - \`NoOpCacheHandler\` added to \`shims/cache.ts\` to skip wasteful ISR writes during prerender; \`CacheHandler\` is save/restored around prerender calls for isolation - Build report integrates \`PrerenderResult\` — routes confirmed static by speculative render are upgraded from \`unknown\` → \`static\` in the output - Hybrid projects (both \`app/\` and \`pages/\`): after the App Router multi-env build, a separate SSR-only build produces the Pages Router bundle so the prerender phase finds both bundles - Adds \`rscOutDir\` / \`ssrOutDir\` / \`clientOutDir\` / \`disableAppRouter\` options to \`VinextOptions\` so tests can build multiple fixtures in parallel into isolated output directories - Miscellaneous cleanups: extract \`loadBundle()\`, rename \`isExplicitlyDynamic\` → \`isConfiguredDynamic\`, \`SetCtx\` interface, \`CacheResultWrapper\`, fix single-row table corner, unify \`onProgress\` to single call site, remove unused \`appDir\` from \`PrerenderAppOptions\` - Support for pre-rendering workers builds via Wrangler servers. ## Tests - 36 new tests in \`tests/prerender.test.ts\` covering \`prerenderPages\`, \`prerenderApp\`, hybrid, and export wiring - All suites pass: **265 app-router + 172 pages-router + 36 prerender + 14 static-export = 487 tests** - Typecheck, lint, and fmt all clean ## Future tasks - Serving pre-rendered responses from memory cache. - Populating remote cache during deployment. - Configurable concurrency for pre-render pipeline. - Dedupe RSC requests during pre-render and extract RSC payload from HTML response. - Improve progress bar tracking for the pre-render phase to be a better reflection of the work that is happening. - Expose a better public API for manual external control over pre-rendering and static exports. - Improve static analysis detection classification for routes when not going through the pre-render pipeline. - Lightweight worker and auto-config options for static exports. - Wire up new static export fixture to actual tests and deployments once static export functionality is finished. - Provide some information in the route report about what was pre-rendered. - Turn on pre-rendering + KV population for the deployed example apps. - Improve pre-rendering test suites. - Performance improvements for resolveParentParams lookups. - Switch unstable_dev to unstable_startWorker and add more informational logs about the server being started. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 13:09:27 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#670
No description provided.