[PR #768] [CLOSED] feat: X-Vinext-Router-Skip header optimization for static layouts #830

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

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/768
Author: @NathanDrake2406
Created: 4/3/2026
Status: Closed

Base: mainHead: feat/layout-persistence-pr-7-skip-header


📝 Commits (4)

  • ecc25d6 feat: X-Vinext-Router-Skip header optimization for static layouts
  • 2e0e0ad test: refresh entry template snapshots
  • c68aa2a fix: disable unsafe app-router skip filtering
  • d63f29a fix: restore mounted-slot requests and tighten codegen seams

📊 Changes

24 files changed (+4337 additions, -245 deletions)

View changed files

packages/vinext/src/build/layout-classification-types.ts (+50 -0)
📝 packages/vinext/src/build/layout-classification.ts (+48 -10)
📝 packages/vinext/src/build/report.ts (+31 -15)
packages/vinext/src/build/route-classification-manifest.ts (+234 -0)
📝 packages/vinext/src/entries/app-rsc-entry.ts (+114 -23)
📝 packages/vinext/src/index.ts (+173 -0)
📝 packages/vinext/src/server/app-browser-entry.ts (+6 -12)
📝 packages/vinext/src/server/app-elements.ts (+165 -2)
📝 packages/vinext/src/server/app-page-cache.ts (+10 -1)
📝 packages/vinext/src/server/app-page-execution.ts (+34 -0)
📝 packages/vinext/src/server/app-page-render.ts (+35 -4)
packages/vinext/src/server/app-page-skip-filter.ts (+333 -0)
📝 packages/vinext/src/shims/error-boundary.tsx (+3 -2)
📝 tests/__snapshots__/entry-templates.test.ts.snap (+732 -132)
📝 tests/app-elements.test.ts (+266 -0)
📝 tests/app-page-cache.test.ts (+156 -0)
📝 tests/app-page-execution.test.ts (+134 -0)
📝 tests/app-page-render.test.ts (+585 -0)
tests/app-page-skip-filter.test.ts (+486 -0)
📝 tests/app-router.test.ts (+21 -0)

...and 4 more files

📄 Description

Summary

Depends on PR 6 (#767). Base branch should be rebased onto PR 6 once merged.

Implements the skip header optimization that lets the client tell the server "I already have these static layouts cached," and the server omits them from the RSC payload. This reduces bandwidth and parse time for navigation between routes that share static layouts.

  • Skip header constants + parser: parseSkipHeader (filters to layout:* entries only), buildSkipHeaderValue (emits only static IDs), X_VINEXT_ROUTER_SKIP_HEADER constant
  • Classification wiring: Thread LayoutClassificationOptions through renderAppPageLifecycle → probe → __layoutFlags injection into the RSC elements payload
  • Client sends skip header: createRscRequestHeaders includes X-Vinext-Router-Skip with static layout IDs from the current router state. Only sent on navigation RSC fetches (not SSR, HMR, server actions, or prefetches)
  • Server respects skip header: After probe + flags injection, deletes layout elements the client requested to skip — but only if the server independently classifies them as static (defense-in-depth)
  • Generated entry wiring: app-rsc-entry.ts parses the skip header, wires classification with getLayoutId + runWithIsolatedDynamicScope, passes skip set to render lifecycle

Safety guarantees

  1. Skip is a hint, not a command. Server validates every skip against its own classification
  2. Metadata always present. __route, __rootLayout, __interceptionContext, __layoutFlags are never skippable
  3. Dynamic layouts never skipped. Even if client requests skip, server renders if classified as "d"
  4. Backward compatible. Empty skip header = render everything. Missing __layoutFlags = empty flags
  5. SSR unaffected. Skip header only sent for navigation RSC requests

Test plan

  • parseSkipHeader: null, empty, single, comma-separated, whitespace, non-layout filtered
  • buildSkipHeaderValue: empty → null, all dynamic → null, mix → only static, all static
  • __layoutFlags injection: static, dynamic, no classification (backward compat), multiple layouts
  • Skip filtering: static omitted, dynamic preserved, metadata preserved, non-layout preserved, SSR bypass
  • Zero regressions: 276 app-router tests pass, all existing render tests pass
  • vp check clean: format, lint, types all pass

🔄 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/768 **Author:** [@NathanDrake2406](https://github.com/NathanDrake2406) **Created:** 4/3/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `feat/layout-persistence-pr-7-skip-header` --- ### 📝 Commits (4) - [`ecc25d6`](https://github.com/cloudflare/vinext/commit/ecc25d6b2fe25a9662baaf3ad5e70d09f75f136e) feat: X-Vinext-Router-Skip header optimization for static layouts - [`2e0e0ad`](https://github.com/cloudflare/vinext/commit/2e0e0ad443e88d7adf14139f4d594fe4fb922824) test: refresh entry template snapshots - [`c68aa2a`](https://github.com/cloudflare/vinext/commit/c68aa2a62022c63d35337cb73bd42bdbf4c50dae) fix: disable unsafe app-router skip filtering - [`d63f29a`](https://github.com/cloudflare/vinext/commit/d63f29a335e05f97d0178485f29629fdb2a6bd26) fix: restore mounted-slot requests and tighten codegen seams ### 📊 Changes **24 files changed** (+4337 additions, -245 deletions) <details> <summary>View changed files</summary> ➕ `packages/vinext/src/build/layout-classification-types.ts` (+50 -0) 📝 `packages/vinext/src/build/layout-classification.ts` (+48 -10) 📝 `packages/vinext/src/build/report.ts` (+31 -15) ➕ `packages/vinext/src/build/route-classification-manifest.ts` (+234 -0) 📝 `packages/vinext/src/entries/app-rsc-entry.ts` (+114 -23) 📝 `packages/vinext/src/index.ts` (+173 -0) 📝 `packages/vinext/src/server/app-browser-entry.ts` (+6 -12) 📝 `packages/vinext/src/server/app-elements.ts` (+165 -2) 📝 `packages/vinext/src/server/app-page-cache.ts` (+10 -1) 📝 `packages/vinext/src/server/app-page-execution.ts` (+34 -0) 📝 `packages/vinext/src/server/app-page-render.ts` (+35 -4) ➕ `packages/vinext/src/server/app-page-skip-filter.ts` (+333 -0) 📝 `packages/vinext/src/shims/error-boundary.tsx` (+3 -2) 📝 `tests/__snapshots__/entry-templates.test.ts.snap` (+732 -132) 📝 `tests/app-elements.test.ts` (+266 -0) 📝 `tests/app-page-cache.test.ts` (+156 -0) 📝 `tests/app-page-execution.test.ts` (+134 -0) 📝 `tests/app-page-render.test.ts` (+585 -0) ➕ `tests/app-page-skip-filter.test.ts` (+486 -0) 📝 `tests/app-router.test.ts` (+21 -0) _...and 4 more files_ </details> ### 📄 Description ## Summary > **Depends on PR 6 (#767).** Base branch should be rebased onto PR 6 once merged. Implements the skip header optimization that lets the client tell the server "I already have these static layouts cached," and the server omits them from the RSC payload. This reduces bandwidth and parse time for navigation between routes that share static layouts. - **Skip header constants + parser**: `parseSkipHeader` (filters to `layout:*` entries only), `buildSkipHeaderValue` (emits only static IDs), `X_VINEXT_ROUTER_SKIP_HEADER` constant - **Classification wiring**: Thread `LayoutClassificationOptions` through `renderAppPageLifecycle` → probe → `__layoutFlags` injection into the RSC elements payload - **Client sends skip header**: `createRscRequestHeaders` includes `X-Vinext-Router-Skip` with static layout IDs from the current router state. Only sent on navigation RSC fetches (not SSR, HMR, server actions, or prefetches) - **Server respects skip header**: After probe + flags injection, deletes layout elements the client requested to skip — but **only if the server independently classifies them as static** (defense-in-depth) - **Generated entry wiring**: `app-rsc-entry.ts` parses the skip header, wires classification with `getLayoutId` + `runWithIsolatedDynamicScope`, passes skip set to render lifecycle ### Safety guarantees 1. **Skip is a hint, not a command.** Server validates every skip against its own classification 2. **Metadata always present.** `__route`, `__rootLayout`, `__interceptionContext`, `__layoutFlags` are never skippable 3. **Dynamic layouts never skipped.** Even if client requests skip, server renders if classified as `"d"` 4. **Backward compatible.** Empty skip header = render everything. Missing `__layoutFlags` = empty flags 5. **SSR unaffected.** Skip header only sent for navigation RSC requests ## Test plan - [x] `parseSkipHeader`: null, empty, single, comma-separated, whitespace, non-layout filtered - [x] `buildSkipHeaderValue`: empty → null, all dynamic → null, mix → only static, all static - [x] `__layoutFlags` injection: static, dynamic, no classification (backward compat), multiple layouts - [x] Skip filtering: static omitted, dynamic preserved, metadata preserved, non-layout preserved, SSR bypass - [x] Zero regressions: 276 app-router tests pass, all existing render tests pass - [x] `vp check` clean: format, lint, types all pass --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 13:10:21 +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#830
No description provided.