Skip to content

fix(app-router): emit vary marker on edge RSC route response#1565

Open
james-elicx wants to merge 1 commit into
mainfrom
fix/rsc-vary-marker
Open

fix(app-router): emit vary marker on edge RSC route response#1565
james-elicx wants to merge 1 commit into
mainfrom
fix/rsc-vary-marker

Conversation

@james-elicx
Copy link
Copy Markdown
Member

Closes #1531

Summary

  • Add the expected x-edge-runtime: 1 marker header on edge runtime App Router responses (both RSC and HTML response builders) to match Next.js, which sets this header in edge-ssr-app.ts.
  • Without this header the upstream test/e2e/app-dir/app/index.test.ts "should return the vary header from edge runtime" assertion fails — it saw null instead of '1'.

Test plan

  • New unit tests in tests/app-page-response.test.ts assert the header is present on both RSC and HTML responses.
  • pnpm run check passes (lint, format, types).
  • Existing app-page-response, app-page-render, and app-router suites stay green.

Closes #1531

The Next.js edge-runtime app template (edge-ssr-app.ts) sets
`x-edge-runtime: 1` on every App Router response. vinext serves App
Router responses from a Cloudflare Worker (an edge-equivalent runtime)
but was not emitting this marker, so Next.js' upstream test suite
(`test/e2e/app-dir/app/index.test.ts`) saw `null` for the header.

Add the header to both the RSC and HTML response builders so the
assertion passes for any App Router page, regardless of which payload
shape the client requests.
@james-elicx
Copy link
Copy Markdown
Member Author

/bigbonk review

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 22, 2026

Open in StackBlitz

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

commit: ec52be6

@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
web preview production

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

The implementation is correct for the stated goal: adding x-edge-runtime: 1 to the two buildAppPage*Response helpers so the ported Next.js test assertion passes. Tests are well-structured and the comments citing edge-ssr-app.ts are helpful.

Two things worth calling out:

1. Incomplete coverage across App Router response paths

buildAppPageRscResponse and buildAppPageHtmlResponse are only two of many App Router response construction sites. Other paths that build RSC/HTML responses independently (and therefore won't carry this header) include:

  • app-page-cache.tsbuildAppPageCachedHeaders() (ISR HIT/STALE responses)
  • app-server-action-execution.ts — server action RSC responses (no-revalidation, re-render, redirect)
  • app-page-dispatch.ts — interception route responses
  • app-page-boundary.ts — boundary fallback RSC responses
  • app-page-execution.ts — RSC redirect responses
  • app-page-stream.tsrenderAppPageHtmlResponse() (separate HTML response path)
  • app-route-handler-response.ts — route handler responses

If the intent is "every App Router response from vinext should carry x-edge-runtime: 1" (since vinext always runs on Workers), these other paths are gaps. Probably fine as a follow-up since this PR is scoped to the specific test failure, but worth a tracking issue.

2. Nuance on what Next.js actually does

In Next.js, x-edge-runtime: 1 is set inside the edge-ssr-app.ts template — it only applies to pages that opt into runtime = 'edge'. Standard Node.js App Router pages do not get this header. vinext's choice to emit it unconditionally (since all responses are edge-equivalent on Workers) is a reasonable divergence, and the comment in the code explains the rationale well. Just flagging it as context.

Verdict

Looks good. The fix is minimal, targeted, and correctly addresses the test failure from #1531.

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented May 22, 2026

Review posted on PR #1565. Here's a summary:

The fix is correct and well-scoped. It adds x-edge-runtime: 1 to both buildAppPageRscResponse and buildAppPageHtmlResponse, which directly addresses the test failure from #1531. Tests pass (26/26).

I flagged two observations in the review:

  1. Incomplete coverage — There are ~7 other App Router response construction paths (cached responses, server actions, interception routes, boundary fallbacks, route handlers, etc.) that build responses independently and won't carry this header. Fine as a follow-up if the intent is full coverage.

  2. Behavioral nuance — In Next.js, x-edge-runtime: 1 is only set for pages that opt into runtime = 'edge', not all App Router pages. vinext emitting it unconditionally is a reasonable deliberate divergence (since Workers are always edge-equivalent), and the code comments explain this well.

github run

@james-elicx james-elicx marked this pull request as ready for review May 22, 2026 14:51
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.

App Router: missing vary marker header on edge runtime RSC route response

1 participant