Link to the code that reproduces this issue
amannn/nextjs-bug-repro-usepathnamessg@c6b084d
To Reproduce
Compare the output of usePathname in development vs during the static prerender when accessing the route /test which uses a rewrite in the middleware.
Current vs. Expected behavior
usePathname seems to pick up a request-time pathname from a middleware rewrite. However, as this information is not available during a static build, usePathname will return a different value in this case. Then again, when running the app in production, usePathname will return the pathname that's displayed in the browser (i.e. after a rewrite), but only on the client side.
In the reproduction this leads to a text content mismatch, but more generally this breaks a dev/prod guarantee. I'd expect a static prerender to only be a performance optimization and not to change application logic.
I guess some unification would be necessary here.
Note that this only applies for static prerendering, if you use SSR in production then the behavior is the same as in dev.
A more real world use case where this behavior was encountered: amannn/next-intl#1568
Provide environment information
Operating System:
Platform: darwin
Arch: x64
Version: Darwin Kernel Version 23.6.0: Mon Jul 29 21:13:00 PDT 2024; root:xnu-10063.141.2~1/RELEASE_X86_64
Available memory (MB): 16384
Available CPU cores: 12
Binaries:
Node: 20.11.1
npm: 10.2.4
Yarn: 1.22.22
pnpm: 9.14.2
Relevant Packages:
next: 15.0.4-canary.23 // Latest available version is detected (15.0.4-canary.23).
eslint-config-next: 15.0.4-canary.23
react: 19.0.0-rc-380f5d67-20241113
react-dom: 19.0.0-rc-380f5d67-20241113
typescript: 5.6.3
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Middleware
Which stage(s) are affected? (Select all that apply)
next dev (local), next build (local), next start (local)
Additional context
Maybe a hook like useInternalPathname() (naming TBD) could help that always reliably returns the pathname that renders in Next.js, regardless of any rewrites—essentially matching the directory structure in src/app.
Link to the code that reproduces this issue
amannn/nextjs-bug-repro-usepathnamessg@c6b084d
To Reproduce
Compare the output of
usePathnamein development vs during the static prerender when accessing the route/testwhich uses a rewrite in the middleware.Current vs. Expected behavior
usePathnameseems to pick up a request-time pathname from a middleware rewrite. However, as this information is not available during a static build,usePathnamewill return a different value in this case. Then again, when running the app in production,usePathnamewill return the pathname that's displayed in the browser (i.e. after a rewrite), but only on the client side.In the reproduction this leads to a text content mismatch, but more generally this breaks a dev/prod guarantee. I'd expect a static prerender to only be a performance optimization and not to change application logic.
I guess some unification would be necessary here.
Note that this only applies for static prerendering, if you use SSR in production then the behavior is the same as in dev.
A more real world use case where this behavior was encountered: amannn/next-intl#1568
Provide environment information
Operating System: Platform: darwin Arch: x64 Version: Darwin Kernel Version 23.6.0: Mon Jul 29 21:13:00 PDT 2024; root:xnu-10063.141.2~1/RELEASE_X86_64 Available memory (MB): 16384 Available CPU cores: 12 Binaries: Node: 20.11.1 npm: 10.2.4 Yarn: 1.22.22 pnpm: 9.14.2 Relevant Packages: next: 15.0.4-canary.23 // Latest available version is detected (15.0.4-canary.23). eslint-config-next: 15.0.4-canary.23 react: 19.0.0-rc-380f5d67-20241113 react-dom: 19.0.0-rc-380f5d67-20241113 typescript: 5.6.3 Next.js Config: output: N/AWhich area(s) are affected? (Select all that apply)
Middleware
Which stage(s) are affected? (Select all that apply)
next dev (local), next build (local), next start (local)
Additional context
Maybe a hook like
useInternalPathname()(naming TBD) could help that always reliably returns the pathname that renders in Next.js, regardless of any rewrites—essentially matching the directory structure insrc/app.