[PR #487] [MERGED] fix: Pages Router ISR background regeneration re-renders HTML #609

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

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/487
Author: @NathanDrake2406
Created: 3/12/2026
Status: Merged
Merged: 3/12/2026
Merged by: @james-elicx

Base: mainHead: fix/isr-pages-router-stale-html


📝 Commits (5)

  • f3f09f4 fix: Pages Router ISR background regeneration re-renders HTML
  • 60a17e8 ci: retrigger checks
  • 20774da fix: preserve document shell during prod ISR regeneration
  • ec636f0 ci: retrigger checks
  • 09720ca ci: retrigger checks

📊 Changes

4 files changed (+216 additions, -8 deletions)

View changed files

📝 packages/vinext/src/entries/pages-server-entry.ts (+53 -2)
📝 packages/vinext/src/server/dev-server.ts (+68 -4)
📝 tests/__snapshots__/entry-templates.test.ts.snap (+53 -2)
📝 tests/features.test.ts (+42 -0)

📄 Description

Summary

  • Pages Router ISR background regeneration was caching stale HTML permanently. The regen re-ran getStaticProps to get fresh data but stored the old HTML back into the cache — only pageData JSON was updated, never the rendered HTML. Every subsequent HIT served the original HTML forever.
  • Fixed in both dev server (dev-server.ts) and production server entry (pages-server-entry.ts).
  • Also fixed two related issues found during review:
    • getStaticProps was called without locale context during regeneration (missing locale, locales, defaultLocale)
    • Dev server didn't update the revalidate duration map after regeneration, so Cache-Control headers could diverge if revalidate changed

Test plan

  • Added "background regeneration re-renders HTML with fresh props" integration test
    • Populates ISR cache, waits for TTL expiry, triggers STALE response
    • Waits for background regeneration, asserts the HIT response has a different timestamp in both HTML and __NEXT_DATA__
    • Proves both server-rendered HTML and hydration data are fresh and in sync
  • All existing ISR tests pass (14/14)
  • ISR cache unit tests pass (31/31)
  • Typecheck clean
  • CI: full Vitest suite + Playwright E2E

🔄 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/487 **Author:** [@NathanDrake2406](https://github.com/NathanDrake2406) **Created:** 3/12/2026 **Status:** ✅ Merged **Merged:** 3/12/2026 **Merged by:** [@james-elicx](https://github.com/james-elicx) **Base:** `main` ← **Head:** `fix/isr-pages-router-stale-html` --- ### 📝 Commits (5) - [`f3f09f4`](https://github.com/cloudflare/vinext/commit/f3f09f4b858f37d34378e1230203d5d256c69d8d) fix: Pages Router ISR background regeneration re-renders HTML - [`60a17e8`](https://github.com/cloudflare/vinext/commit/60a17e810ed6d145c5d3cfcc188715c67c32f525) ci: retrigger checks - [`20774da`](https://github.com/cloudflare/vinext/commit/20774daa7e931062a7d33d7e72af6932cd460e4b) fix: preserve document shell during prod ISR regeneration - [`ec636f0`](https://github.com/cloudflare/vinext/commit/ec636f0a6462bce5c86d7e8c4ee17b951e9f581e) ci: retrigger checks - [`09720ca`](https://github.com/cloudflare/vinext/commit/09720ca4249788cf0668cf2e41f357f13f216816) ci: retrigger checks ### 📊 Changes **4 files changed** (+216 additions, -8 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/entries/pages-server-entry.ts` (+53 -2) 📝 `packages/vinext/src/server/dev-server.ts` (+68 -4) 📝 `tests/__snapshots__/entry-templates.test.ts.snap` (+53 -2) 📝 `tests/features.test.ts` (+42 -0) </details> ### 📄 Description ## Summary - **Pages Router ISR background regeneration was caching stale HTML permanently.** The regen re-ran `getStaticProps` to get fresh data but stored the old HTML back into the cache — only `pageData` JSON was updated, never the rendered HTML. Every subsequent HIT served the original HTML forever. - Fixed in both dev server (`dev-server.ts`) and production server entry (`pages-server-entry.ts`). - Also fixed two related issues found during review: - `getStaticProps` was called without locale context during regeneration (missing `locale`, `locales`, `defaultLocale`) - Dev server didn't update the revalidate duration map after regeneration, so `Cache-Control` headers could diverge if `revalidate` changed ## Test plan - [x] Added `"background regeneration re-renders HTML with fresh props"` integration test - Populates ISR cache, waits for TTL expiry, triggers STALE response - Waits for background regeneration, asserts the HIT response has a **different** timestamp in both HTML and `__NEXT_DATA__` - Proves both server-rendered HTML and hydration data are fresh and in sync - [x] All existing ISR tests pass (14/14) - [x] ISR cache unit tests pass (31/31) - [x] Typecheck clean - [ ] CI: full Vitest suite + Playwright E2E --- <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:02 +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#609
No description provided.