fix: App Router RSC dev invalidation parity across requests#449
fix: App Router RSC dev invalidation parity across requests#449JaredStowell wants to merge 10 commits intocloudflare:mainfrom
Conversation
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3da870e4c6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f3340fb355
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const __hostPrepared = request.headers.get(__hostPreparedHeader) === "1"; | ||
| const __hostRewriteStatus = request.headers.get(__hostRewriteStatusHeader); | ||
| const __hostPreparedTarget = request.headers.get(__hostTargetHeader); | ||
| if (__hostPrepared || __hostRewriteStatus || __hostPreparedTarget) { |
There was a problem hiding this comment.
Ignore user-set app-router preparation headers
This trusts x-vinext-app-router-prepared/x-vinext-app-router-target directly from the incoming request, and later _handleRequest(..., __hostPrepared) skips middleware, redirects, and rewrites when that flag is true. Because these are ordinary client-controlled HTTP headers and there is no provenance check, a caller can send x-vinext-app-router-prepared: 1 (optionally with a target) to bypass middleware-protected App Router behavior, including production requests handled by this generated entry.
Useful? React with 👍 / 👎.
packages/vinext/src/index.ts
Outdated
| req.url = url; | ||
| setAppRouterPreparedRequestState(req, { rewriteStatus, requestUrl: url }); |
There was a problem hiding this comment.
Preserve source URL in host-prepared rewrite handoff
This always stores the post-rewrite URL as requestUrl for host-prepared requests, and the RSC entry later reconstructs request.url from that target before running matchHeaders(...). In app-only projects (where prepareDirectAppRouterRequest runs for every request), headers rules are therefore evaluated against the rewrite destination instead of the original source path, so rewrite-source header rules can stop matching while destination headers are applied instead.
Useful? React with 👍 / 👎.
Fix App Router dev-mode RSC invalidation so server modules re-execute with request freshness.
This change removes the old root-scoped invalidation heuristic and replaces it with route-closure invalidation:
It also fixes mixed app/pages behavior by invalidating on the actual Pages -> App handoff path after middleware/config rewrites determine the final App Router URL.
Why
The previous approach was inadequate:
Tests
Added regressions for:
Verification
Passed:
pnpm test tests/nextjs-compat/app-rendering.test.tspnpm test tests/app-router.test.ts -t "re-executes App Router modules when middleware rewrites a Pages path into app/"pnpm test tests/app-router.test.ts -t "App Router Static export"pnpm run fmtpnpm run typecheck