[PR #394] [MERGED] fix: Pages Router prod hydration for inlined page modules #538

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

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/394
Author: @JaredStowell
Created: 3/10/2026
Status: Merged
Merged: 3/10/2026
Merged by: @james-elicx

Base: mainHead: jstowell/fix-pages-router-client-manifest


📝 Commits (7)

  • 9658e4e Clarify chunk manifest structures
  • 728b697 Fix SSR manifest basePath URLs
  • 3a41fdd Fix SSR manifest basePath handling
  • 409de09 Fix SSR manifest basePath handling
  • a28a671 make ci happy
  • 3d31023 bonk
  • 4da1524 Merge branch 'main' into jstowell/fix-pages-router-client-manifest

📊 Changes

6 files changed (+560 additions, -45 deletions)

View changed files

📝 packages/vinext/src/index.ts (+132 -16)
📝 packages/vinext/src/server/prod-server.ts (+27 -23)
packages/vinext/src/utils/manifest-paths.ts (+19 -0)
📝 tests/build-optimization.test.ts (+132 -0)
📝 tests/deploy.test.ts (+25 -5)
📝 tests/pages-router.test.ts (+225 -1)

📄 Description

This fixes a Pages Router bug where SSR worked but interactive pages failed to hydrate when the page module was inlined into the client entry chunk.

For affected routes like /counter, the server looked up the page in ssr-manifest.json to decide which client assets to inject. When Vite inlined that page into the main client entry, the page’s SSR manifest entry was emitted as empty, so the server rendered HTML but never loaded the page’s client code. The result was a silent hydration miss in production on Node.

The fix backfills ssr-manifest.json from the emitted client bundle rather than relying only on manifest.json. That lets us map source page modules to the chunk that actually contains them, including:

  • pages emitted as standalone chunks
  • pages inlined into the client entry
  • associated CSS and static assets from Vite metadata
  • basePath / Vite base-prefixed asset URLs

Test coverage was expanded to prove the runtime path:

  • helper-level tests for bundle-based SSR manifest augmentation
  • Pages Router production-build coverage for the inlined /counter case
  • production HTML assertions for basePath-prefixed emitted asset tags
  • end-to-end production coverage for backfilled CSS/static-asset cases

Verification:

  • reproduced the bug on clean HEAD: /counter stayed at Count: 0 and ssr-manifest.json["pages/counter.tsx"] was empty
  • verified the patched build hydrates correctly: /counter updates to Count: 1
  • ran targeted tests for build optimization and Pages Router production behavior

🔄 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/394 **Author:** [@JaredStowell](https://github.com/JaredStowell) **Created:** 3/10/2026 **Status:** ✅ Merged **Merged:** 3/10/2026 **Merged by:** [@james-elicx](https://github.com/james-elicx) **Base:** `main` ← **Head:** `jstowell/fix-pages-router-client-manifest` --- ### 📝 Commits (7) - [`9658e4e`](https://github.com/cloudflare/vinext/commit/9658e4e2d921bf6f1f8ae912440c5345daef45c4) Clarify chunk manifest structures - [`728b697`](https://github.com/cloudflare/vinext/commit/728b6975b3f7337f21c76dcc8685e69a8f5b2b3c) Fix SSR manifest basePath URLs - [`3a41fdd`](https://github.com/cloudflare/vinext/commit/3a41fdd6271a91b15d465267e16d0b146ff9bff1) Fix SSR manifest basePath handling - [`409de09`](https://github.com/cloudflare/vinext/commit/409de095b3c5e16e5a8c94f45447a51301d4336b) Fix SSR manifest basePath handling - [`a28a671`](https://github.com/cloudflare/vinext/commit/a28a671e387cf5d6aecead842e3103d638fbdbf4) make ci happy - [`3d31023`](https://github.com/cloudflare/vinext/commit/3d310234cdbbb20c134bcec3ff2a8ef5a50958b3) bonk - [`4da1524`](https://github.com/cloudflare/vinext/commit/4da1524ce562611ae0d7534c83a66b6558f1b817) Merge branch 'main' into jstowell/fix-pages-router-client-manifest ### 📊 Changes **6 files changed** (+560 additions, -45 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/index.ts` (+132 -16) 📝 `packages/vinext/src/server/prod-server.ts` (+27 -23) ➕ `packages/vinext/src/utils/manifest-paths.ts` (+19 -0) 📝 `tests/build-optimization.test.ts` (+132 -0) 📝 `tests/deploy.test.ts` (+25 -5) 📝 `tests/pages-router.test.ts` (+225 -1) </details> ### 📄 Description This fixes a Pages Router bug where SSR worked but interactive pages failed to hydrate when the page module was inlined into the client entry chunk. For affected routes like `/counter`, the server looked up the page in `ssr-manifest.json` to decide which client assets to inject. When Vite inlined that page into the main client entry, the page’s SSR manifest entry was emitted as empty, so the server rendered HTML but never loaded the page’s client code. The result was a silent hydration miss in production on Node. The fix backfills `ssr-manifest.json` from the emitted client bundle rather than relying only on `manifest.json`. That lets us map source page modules to the chunk that actually contains them, including: - pages emitted as standalone chunks - pages inlined into the client entry - associated CSS and static assets from Vite metadata - `basePath` / Vite `base`-prefixed asset URLs Test coverage was expanded to prove the runtime path: - helper-level tests for bundle-based SSR manifest augmentation - Pages Router production-build coverage for the inlined `/counter` case - production HTML assertions for `basePath`-prefixed emitted asset tags - end-to-end production coverage for backfilled CSS/static-asset cases Verification: - reproduced the bug on clean `HEAD`: `/counter` stayed at `Count: 0` and `ssr-manifest.json["pages/counter.tsx"]` was empty - verified the patched build hydrates correctly: `/counter` updates to `Count: 1` - ran targeted tests for build optimization and Pages Router production behavior --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 13:08:38 +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#538
No description provided.