[PR #1036] [MERGED] refactor(app-rsc): move request lifecycle into typed handler #1037

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

📋 Pull Request Information

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

Base: mainHead: nathan/finish-app-rsc-entry


📝 Commits (3)

  • fc365b7 refactor(app-rsc): introduce app-rsc-request-normalization module
  • 89d088d refactor(app-rsc): wire normalizeRscRequest into the entry and callsites
  • d2fed81 refactor(app-rsc): move request lifecycle into typed handler

📊 Changes

6 files changed (+1116 additions, -671 deletions)

View changed files

📝 packages/vinext/src/entries/app-rsc-entry.ts (+315 -576)
packages/vinext/src/server/app-rsc-handler.ts (+494 -0)
📝 packages/vinext/src/server/app-rsc-request-normalization.ts (+2 -0)
📝 tests/app-router.test.ts (+56 -94)
tests/app-rsc-handler.test.ts (+248 -0)
📝 tests/app-rsc-request-normalization.test.ts (+1 -1)

📄 Description

The refactor to end them all!

What this changes

Moves the App Router RSC request lifecycle out of the generated virtual entry and into a typed createAppRscHandler runtime helper.

The generated RSC entry now describes app shape and route-specific wiring: route manifests, metadata routes, root params, dispatch closures, action adapters, fallback renderers, and config values. The normal module owns behavior: normalization, config redirects, middleware handoff, rewrites, metadata/public files, server actions, route-handler/page dispatch, 404 cleanup, request ALS setup, and response finalization.

Why

The App RSC entry had grown into a large generated runtime subsystem. That violated the working principle for this refactor: codegen should describe the app shape; normal modules should implement behavior.

It also made behavior hard to test directly. Important lifecycle semantics were protected by string assertions against generated code rather than behavior tests against an importable module.

Relevant Next.js source references:

Approach

  • Add packages/vinext/src/server/app-rsc-handler.ts as the typed runtime owner for App RSC request handling.
  • Keep generated route-specific code in entries/app-rsc-entry.ts as data and closures passed to the helper.
  • Replace fragile generated-runtime string checks with boundary assertions that generated code passes route/config/action wiring to createAppRscHandler.
  • Add direct behavior tests for the request lifecycle: config redirects, rewrites, public files, server-action short-circuiting, action header compatibility, route handlers, and fallback cleanup.

Validation

  • vp check tests/app-rsc-handler.test.ts packages/vinext/src/server/app-rsc-handler.ts packages/vinext/src/entries/app-rsc-entry.ts tests/app-router.test.ts tests/entry-templates.test.ts
  • vp test run tests/app-rsc-handler.test.ts tests/app-rsc-request-normalization.test.ts tests/app-rsc-response-finalizer.test.ts tests/entry-templates.test.ts passed 68 tests
  • vp test run tests/app-router.test.ts passed 289 tests
  • Commit hook ran vp check --fix, tests/entry-templates.test.ts, and knip --no-progress
  • Ran the required elegance review pass, then code-simplifier. No follow-up edits were needed after the simplifier pass.

Risks / follow-ups

This PR is stacked on the request-normalization and response-finalizer App RSC refactor work from #1034 and #1035. Until those land or this branch is retargeted, GitHub will show the prerequisite commits in this diff as well.

The remaining generated entry still owns route-specific page/action closures because those depend on generated imports and app shape. That is intentional for this slice.


🔄 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/1036 **Author:** [@NathanDrake2406](https://github.com/NathanDrake2406) **Created:** 5/3/2026 **Status:** ✅ Merged **Merged:** 5/3/2026 **Merged by:** [@james-elicx](https://github.com/james-elicx) **Base:** `main` ← **Head:** `nathan/finish-app-rsc-entry` --- ### 📝 Commits (3) - [`fc365b7`](https://github.com/cloudflare/vinext/commit/fc365b7910fec3d1af2c67170272be2c3a557935) refactor(app-rsc): introduce app-rsc-request-normalization module - [`89d088d`](https://github.com/cloudflare/vinext/commit/89d088d0d52a5c934fdf48fedd0a356b474738f9) refactor(app-rsc): wire normalizeRscRequest into the entry and callsites - [`d2fed81`](https://github.com/cloudflare/vinext/commit/d2fed81e542185056bfd81f64f1fc50194f55b45) refactor(app-rsc): move request lifecycle into typed handler ### 📊 Changes **6 files changed** (+1116 additions, -671 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/entries/app-rsc-entry.ts` (+315 -576) ➕ `packages/vinext/src/server/app-rsc-handler.ts` (+494 -0) 📝 `packages/vinext/src/server/app-rsc-request-normalization.ts` (+2 -0) 📝 `tests/app-router.test.ts` (+56 -94) ➕ `tests/app-rsc-handler.test.ts` (+248 -0) 📝 `tests/app-rsc-request-normalization.test.ts` (+1 -1) </details> ### 📄 Description The refactor to end them all! ## What this changes Moves the App Router RSC request lifecycle out of the generated virtual entry and into a typed `createAppRscHandler` runtime helper. The generated RSC entry now describes app shape and route-specific wiring: route manifests, metadata routes, root params, dispatch closures, action adapters, fallback renderers, and config values. The normal module owns behavior: normalization, config redirects, middleware handoff, rewrites, metadata/public files, server actions, route-handler/page dispatch, 404 cleanup, request ALS setup, and response finalization. ## Why The App RSC entry had grown into a large generated runtime subsystem. That violated the working principle for this refactor: codegen should describe the app shape; normal modules should implement behavior. It also made behavior hard to test directly. Important lifecycle semantics were protected by string assertions against generated code rather than behavior tests against an importable module. Relevant Next.js source references: - Next.js applies `beforeFiles`, `afterFiles`, then `fallback` rewrites in server routing: [server-utils.ts#L350-L365](https://github.com/vercel/next.js/blob/canary/packages/next/src/server/server-utils.ts#L350-L365) - Next.js defines the server action request header as `next-action`: [app-router-headers.ts#L1-L3](https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/app-router-headers.ts#L1-L3) - Next.js reads that action header from Web `Headers` and Node request headers: [server-action-request-meta.ts#L18-L24](https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/server-action-request-meta.ts#L18-L24) - Next.js decodes path params segment-by-segment while preserving escaped path delimiters: [decode-path-params.ts#L11-L25](https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/router-utils/decode-path-params.ts#L11-L25) ## Approach - Add `packages/vinext/src/server/app-rsc-handler.ts` as the typed runtime owner for App RSC request handling. - Keep generated route-specific code in `entries/app-rsc-entry.ts` as data and closures passed to the helper. - Replace fragile generated-runtime string checks with boundary assertions that generated code passes route/config/action wiring to `createAppRscHandler`. - Add direct behavior tests for the request lifecycle: config redirects, rewrites, public files, server-action short-circuiting, action header compatibility, route handlers, and fallback cleanup. ## Validation - `vp check tests/app-rsc-handler.test.ts packages/vinext/src/server/app-rsc-handler.ts packages/vinext/src/entries/app-rsc-entry.ts tests/app-router.test.ts tests/entry-templates.test.ts` - `vp test run tests/app-rsc-handler.test.ts tests/app-rsc-request-normalization.test.ts tests/app-rsc-response-finalizer.test.ts tests/entry-templates.test.ts` passed 68 tests - `vp test run tests/app-router.test.ts` passed 289 tests - Commit hook ran `vp check --fix`, `tests/entry-templates.test.ts`, and `knip --no-progress` - Ran the required elegance review pass, then code-simplifier. No follow-up edits were needed after the simplifier pass. ## Risks / follow-ups This PR is stacked on the request-normalization and response-finalizer App RSC refactor work from #1034 and #1035. Until those land or this branch is retargeted, GitHub will show the prerequisite commits in this diff as well. The remaining generated entry still owns route-specific page/action closures because those depend on generated imports and app shape. That is intentional for this slice. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 13:11:41 +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#1037
No description provided.