Repository: vercel/next.js
Pull request: [next-server] skip setting vary header for basic routes

### What

After https://github.com/vercel/vercel/pull/13011 landed on Vercel CLI, noticing that we're still checking the `vary` header in the tests, which is obselete now. In this PR we delete the handling for setting the `vary` header but still keep the cases of interception routes since it's still needed.

### Why

Since v13.4.6 we added the `_rsc` query with the unique hash, `vary` header becomes not required anymore.

Closes NDX-1010

Changed files:
filename: packages/next/src/server/base-server.ts
patch: @@ -104,7 +104,6 @@ import {
   NEXT_ROUTER_SEGMENT_PREFETCH_HEADER,
   NEXT_DID_POSTPONE_HEADER,
   NEXT_URL,
-  NEXT_ROUTER_STATE_TREE_HEADER,
   NEXT_IS_PRERENDER_HEADER,
 } from '../client/components/app-router-headers'
 import type {
@@ -1978,21 +1977,16 @@ export default abstract class Server<
     isAppPath: boolean,
     resolvedPathname: string
   ): void {
-    const baseVaryHeader = `${RSC_HEADER}, ${NEXT_ROUTER_STATE_TREE_HEADER}, ${NEXT_ROUTER_PREFETCH_HEADER}, ${NEXT_ROUTER_SEGMENT_PREFETCH_HEADER}`
-    const isRSCRequest = getRequestMeta(req, 'isRSCRequest') ?? false
-
     let addedNextUrlToVary = false
 
     if (isAppPath && this.pathCouldBeIntercepted(resolvedPathname)) {
       // Interception route responses can vary based on the `Next-URL` header.
       // We use the Vary header to signal this behavior to the client to properly cache the response.
-      res.appendHeader('vary', `${baseVaryHeader}, ${NEXT_URL}`)
+      res.appendHeader('vary', `${NEXT_URL}`)
       addedNextUrlToVary = true
-    } else if (isAppPath || isRSCRequest) {
-      // We don't need to include `Next-URL` in the Vary header for non-interception routes since it won't affect the response.
-      // We also set this header for pages to avoid caching issues when navigating between pages and app.
-      res.appendHeader('vary', baseVaryHeader)
     }
+    // For other cases such as App Router requests or RSC requests we don't need to set vary header since we already
+    // have the _rsc query with the unique hash value.
 
     if (!addedNextUrlToVary) {
       // Remove `Next-URL` from the request headers we determined it wasn't necessary to include in the Vary header.

filename: test/e2e/app-dir/app/index.test.ts
patch: @@ -323,27 +323,6 @@ describe('app dir - basic', () => {
     expect(res.headers.get('Content-Type')).toBe('text/x-component')
   })
 
-  it('should return the `vary` header from edge runtime', async () => {
-    const res = await next.fetch('/dashboard')
-    expect(res.headers.get('x-edge-runtime')).toBe('1')
-    expect(res.headers.get('vary')).toBe(
-      'RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch'
-    )
-  })
-
-  it('should return the `vary` header from pages for flight requests', async () => {
-    const res = await next.fetch('/', {
-      headers: {
-        ['RSC'.toString()]: '1',
-      },
-    })
-    expect(res.headers.get('vary')).toBe(
-      isNextDeploy
-        ? 'RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch'
-        : 'RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch, Accept-Encoding'
-    )
-  })
-
   it('should pass props from getServerSideProps in root layout', async () => {
     const $ = await next.render$('/dashboard')
     expect($('title').first().text()).toBe('hello world')

filename: test/e2e/vary-header/test/index.test.ts
patch: @@ -12,21 +12,16 @@ describe('Vary Header Tests', () => {
     expect(res.headers.get('vary')).toContain('Custom-Header')
   })
 
-  it('should preserve custom vary header and append RSC headers in app route handlers', async () => {
+  it('should preserve custom vary header', async () => {
     const res = await next.fetch('/normal')
     const varyHeader = res.headers.get('vary')
 
     // Custom header is preserved
     expect(varyHeader).toContain('User-Agent')
     expect(res.headers.get('cache-control')).toBe('s-maxage=3600')
-
-    // Next.js internal headers are appended
-    expect(varyHeader).toContain('RSC')
-    expect(varyHeader).toContain('Next-Router-State-Tree')
-    expect(varyHeader).toContain('Next-Router-Prefetch')
   })
 
-  it('should preserve middleware vary header in combination with route handlers', async () => {
+  it('should preserve middleware vary header', async () => {
     const res = await next.fetch('/normal')
     const varyHeader = res.headers.get('vary')
     const customHeader = res.headers.get('my-custom-header')
@@ -37,10 +32,5 @@ describe('Vary Header Tests', () => {
     // Both middleware and route handler vary headers are preserved
     expect(varyHeader).toContain('my-custom-header')
     expect(varyHeader).toContain('User-Agent')
-
-    // Next.js internal headers are still present
-    expect(varyHeader).toContain('RSC')
-    expect(varyHeader).toContain('Next-Router-State-Tree')
-    expect(varyHeader).toContain('Next-Router-Prefetch')
   })
 })