Repository: next.js
Issue: Link prefetch causing bug cache in Vercel deploy
Labels: Navigation

### Verify canary release

- [X] I verified that the issue exists in the latest Next.js canary release

### Provide environment information

```bash
Operating System:
      Platform: darwin
      Arch: x64
      Version: Darwin Kernel Version 20.6.0: Fri Dec 16 00:35:00 PST 2022; root:xnu-7195.141.49~1/RELEASE_X86_64
    Binaries:
      Node: 16.15.0
      npm: 9.5.1
      Yarn: 1.22.19
      pnpm: N/A
    Relevant packages:
      next: 13.2.5-canary.12
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0
```


### Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true)

### Link to the code that reproduces this issue

https://github.com/rodlac/prefetch-cache-bug

### To Reproduce

- Create a route with Dynamic Segment in `app` path (e.g. `/post/[id]`)
- Add the code below to module.exports in the next.config.js file
```
async headers() {
  return [
    {
      source: '/post/:id',
      headers: [
        {
          key: 'Cache-Control',
          value: 'public, s-maxage=30',
        },
      ],
    },
  ]
}
```
- Create a link to the route using the Link component (e.g. `<Link href='/post/1'>Title</Link>`)
- Deploy to Vercel
- Open the page that contains the link and try to navigate to the route with Dynamic Segment

### Describe the Bug

When the page containing the link is loaded, the links are preloaded with an XHR call. However, when clicking on a link, a blank page appears. An example page can be accessed at the following link:

https://prefetch-cache-bug.vercel.app/

This is happening because the preloaded response is being cached by Vercel, and when we click on the link, the same response is being loaded.

```
0:[["children","post",["post",{"children":[["id","1","d"],{"children":["__PAGE__?{\"id\":\"1\"}",{}]}]}],null,null]]
```

When clicking on the link, the server's response should actually be something like:

```
0:[["children","post",["post",{"children":[["id","1","d"],{"children":["__PAGE__",{}]}]}],"$L1",["$L2",null]]]
3:I{"id":"1300","name":"","chunks":["272:webpack-8074fabf81ca3fbd","916:916-fd276e448a10a093"],"async":false}
4:I{"id":"6022","name":"","chunks":["272:webpack-8074fabf81ca3fbd","916:916-fd276e448a10a093"],"async":false}
2:[[["$","meta",null,{"charSet":"utf-8"}],null,null,null,null,null,null,null,null,null,null,["$","meta",null,{"name":"viewport","content":"width=device-width, initial-scale=1"}],null,null,null,null,null,null,null,null,null,null,[]],[null,null,null,null],null,null,[null,null,null,null,null],null,null,null,null,null]
1:["$","$L3",null,{"parallelRouterKey":"children","segmentPath":["children","post","children"],"hasLoading":false,"template":["$","$L4",null,{}],"childProp":{"current":["$","$L3",null,{"parallelRouterKey":"children","segmentPath":["children","post","children",["id","1","d"],"children"],"hasLoading":false,"template":["$","$L4",null,{}],"childProp":{"current":["$L5",null,null,[]],"segment":"__PAGE__"}}],"segment":["id","1","d"]}}]
5:[["$","h1",null,{"children":"sunt aut facere repellat provident occaecati excepturi optio reprehenderit"}],["$","p",null,{"children":"quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"}]]
```

I know I could disable by passing `prefetch={false}` attribute, but that's not the issue now.

### Expected Behavior

The reported issue seems to be related to the cache server not taking into account the Vary header returned by the application. `Vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch`

The expected behavior is that the cache server should use the Vary header to identify which request headers are relevant to the response and cache multiple versions of the same resource based on those headers. In this case, two requests with different Next-Router-State-Tree and Next-Router-Prefetch headers are returning the same response, but they should have different responses due to the difference in the headers.

### Which browser are you using? (if relevant)

_No response_

### How are you deploying your application? (if relevant)

Vercel