Skip to content

refactor: extract app route handler execution helpers#624

Merged
southpolesteve merged 1 commit intomainfrom
codex/app-route-handler-request-execution
Mar 21, 2026
Merged

refactor: extract app route handler execution helpers#624
southpolesteve merged 1 commit intomainfrom
codex/app-route-handler-request-execution

Conversation

@southpolesteve
Copy link
Copy Markdown
Collaborator

Summary

  • extract the live App Router route-handler execution path into a typed app-route-handler-execution.ts runtime module
  • reuse that helper for background route-handler regeneration so less request lifecycle logic stays embedded in app-rsc-entry.ts
  • add focused execution-helper unit coverage and update generator assertions/snapshots to match the helper-based shape

Verification

  • vp check packages/vinext/src/server/app-route-handler-execution.ts packages/vinext/src/entries/app-rsc-entry.ts tests/app-route-handler-execution.test.ts tests/app-router.test.ts tests/__snapshots__/entry-templates.test.ts.snap
  • vp test run tests/app-route-handler-execution.test.ts tests/app-route-handler-runtime.test.ts tests/app-route-handler-response.test.ts tests/app-route-handler-policy.test.ts
  • vp test run tests/entry-templates.test.ts
  • vp test run tests/app-router.test.ts -t 'route handler'
  • vp test run tests/nextjs-compat/app-routes.test.ts
  • vp run vinext#build

Stacked on #622.

Written by Codex.

Base automatically changed from codex/app-route-handler-policy-runtime to main March 21, 2026 13:56
@southpolesteve southpolesteve force-pushed the codex/app-route-handler-request-execution branch from 8c59175 to 09f3378 Compare March 21, 2026 13:58
@southpolesteve
Copy link
Copy Markdown
Collaborator Author

/bigbonk

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Mar 21, 2026

Open in StackBlitz

npm i https://pkg.pr.new/vinext@624

commit: 09f3378

@github-actions
Copy link
Copy Markdown

Example Preview Production Original
app-router-cloudflare preview production
pages-router-cloudflare preview production
app-router-playground preview production original
realworld-api-rest preview production
nextra-docs-template preview production
benchmarks preview production
hackernews preview production original

Copy link
Copy Markdown
Contributor

@ask-bonk ask-bonk Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Extract app route handler execution helpers

Clean refactoring that moves the inline route-handler execution logic from the generated app-rsc-entry.ts template into a typed, testable app-route-handler-execution.ts runtime module. The behavioral equivalence is well-preserved.

What looks good

  1. Faithful extraction. The executeAppRouteHandler() function reproduces the original inline logic from the generated entry template:

    • setHeadersAccessPhase("route-handler") / restore in finally block
    • consumeDynamicUsage() → run handler → consumeDynamicUsage() (reset-before, check-after pattern preserved in runAppRouteHandler)
    • shouldApplyAppRouteHandlerRevalidateHeaderapplyRouteHandlerRevalidateHeader
    • shouldWriteAppRouteHandlerCachemarkRouteHandlerCacheMiss + clone + async cache write via waitUntil
    • Cookie collection, draft mode, clearRequestContext, and finalizeRouteHandlerResponseapplyRouteHandlerMiddlewareContext — all in the correct order
    • Error path: getAndClearPendingCookies() on catch, resolveAppRouteHandlerSpecialError, redirect/status discrimination, reportRequestError for generic failures, clearRequestContext before returning error responses
  2. Background regeneration reuse. The ISR stale-while-revalidate background regen path now uses runAppRouteHandler() instead of duplicating the createTrackedAppRouteRequest + consumeDynamicUsage dance inline. This is a nice DRY improvement.

  3. Clean interface. The ExecuteAppRouteHandlerOptions interface is well-typed — each dependency is an explicit function/value rather than relying on module-level state from the generated entry. This makes the unit tests possible and makes the contract between the generated code and the runtime explicit.

  4. Good test coverage. The test file covers the happy path (static response with cache write), dynamic usage detection (skips cache, marks route), and error handling (redirect via digest, generic error with reportRequestError). The createDynamicUsageState() helper is a clean way to simulate the global reset/check pattern.

Minor observations (non-blocking)

  1. params type annotation. RunAppRouteHandlerOptions.params is typed as Record<string, string | string[]>, but the generated entry passes the match result directly (which could have additional prototype quirks from matchPattern). This works fine in practice because the params are spread into a plain object by makeThenableParams before reaching the handler. Just noting for awareness.

  2. Snapshot reduction is dramatic (~762 lines removed). This is a direct consequence of the refactoring — the inline route handler code was repeated in multiple snapshot variants. The smaller snapshots are a maintenance win.

  3. clearRequestContext call in the error path. In the original code, the error path called setHeadersContext(null); setNavigationContext(null) before the resolveAppRouteHandlerSpecialError check (for special errors like redirect). The new code calls clearRequestContext() after calling getAndClearPendingCookies() and before checking specialError. This is the same effective ordering — good.

Verdict

Straightforward mechanical extraction with correct behavioral equivalence. Tests cover the key paths. No regressions expected.

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented Mar 21, 2026

I've reviewed and approved PR #624. Here's a summary of my findings:

Verdict: Approved

The PR cleanly extracts ~115 lines of inline route-handler execution logic from the generated app-rsc-entry.ts template into a typed, testable app-route-handler-execution.ts runtime module. Key points:

  • Behavioral equivalence is preserved. The executeAppRouteHandler() function faithfully reproduces the original inline logic: headers phase management, dynamic usage detection (reset-before/check-after), Cache-Control application, ISR cache writes via waitUntil, cookie collection, error handling with special error discrimination (redirects, notFound), and reportRequestError for generic failures.

  • DRY improvement for background regeneration. The ISR stale-while-revalidate regen path now reuses runAppRouteHandler() instead of duplicating the tracked request creation inline.

  • Clean typed interface. Each dependency is an explicit function/value in ExecuteAppRouteHandlerOptions, making the contract between generated code and runtime explicit and testable.

  • Good test coverage. Tests cover static responses with cache writes, dynamic usage detection, and error handling (redirect via digest, generic errors).

  • Snapshot reduction (~762 lines removed) is a maintenance win from eliminating duplicated inline code across snapshot variants.

github run

@southpolesteve southpolesteve merged commit 4af18c7 into main Mar 21, 2026
30 checks passed
@southpolesteve southpolesteve deleted the codex/app-route-handler-request-execution branch March 21, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant