vercel / next.js

The React Framework
https://nextjs.org
MIT License
125.91k stars 26.87k forks source link

Link Prefetch causes mismatch between rendered route and fetched props #68073

Closed exoRift closed 1 month ago

exoRift commented 2 months ago

Link to the code that reproduces this issue

https://codesandbox.io/p/devbox/vibrant-james-gmhkyx

To Reproduce

  1. Build the production build with pnpm run build
  2. Run the production build with pnpm start
  3. Make sure you're not in dev mode and you're in production mode
  4. Open the preview at the index /
  5. Click the link to page B
  6. Notice the disparity between the console and the rendered page. Page C's props are fetched but page B is rendered

Current vs. Expected behavior

The middleware reroute should take place and page C should be rendered. However, page B is rendered instead

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.5.0: Wed May  1 20:19:05 PDT 2024; root:xnu-10063.121.3~5/RELEASE_ARM64_T8112
  Available memory (MB): 24576
  Available CPU cores: 8
Binaries:
  Node: 20.15.1
  npm: 10.7.0
  Yarn: N/A
  pnpm: 8.15.1
Relevant Packages:
  next: 14.2.5 // Latest available version is detected (14.2.5).
  eslint-config-next: 14.2.4
  react: 18.3.1
  react-dom: 18.3.1
  typescript: 5.5.2
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Middleware, Navigation, Pages Router

Which stage(s) are affected? (Select all that apply)

next build (local), next start (local)

Additional context

This has repercussions on things like authentication where an expiring session that leads to a display of the signin page causes clientside errors

ztanner commented 2 months ago

Hey @exoRift! Does leveraging the x-middleware-cache: 'no-cache' when performing the middleware rewrite work for your use-case? eg:

return NextResponse.rewrite(url, {
  headers: { 'x-middleware-cache': 'no-cache' },
})

It's currently undocumented, but it's a way to signal to the client router cache that it should disregard its cached entry when navigating (more details in this PR description)

exoRift commented 2 months ago

Hey @exoRift! Does leveraging the x-middleware-cache: 'no-cache' when performing the middleware rewrite work for your use-case? eg:

return NextResponse.rewrite(url, {
  headers: { 'x-middleware-cache': 'no-cache' },
})

It's currently undocumented, but it's a way to signal to the client router cache that it should disregard its cached entry when navigating (more details in this PR description)

Unfortunately, that did not work. Not on my local code nor on my reproduction linked above

Screenshot 2024-07-25 at 1 38 38 PM
exoRift commented 2 months ago

@ztanner Any other ideas?

exoRift commented 1 month ago

Is there any update on this?

Edit by maintainer bot: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!

ztanner commented 1 month ago

hi @exoRift -- in your repro, your middleware isn't rewriting the prefetch request (the /_next/data/b.json call) because you have the rewrite on every second request to /b. Changing it to !(++counter % 1) fixes it but the counter example seems fairly contrived so I'm not sure if that resolves your use-case. The important consideration to keep in mind here is:

If I make either of these adjustments in your reproduction, it appears to work as expected.

exoRift commented 1 month ago

Tentative, but it seems I was able to resolve this issue by setting

  experimental: {
    middlewarePrefetch: 'strict'
  }
github-actions[bot] commented 4 weeks ago

This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.