How are you deploying your application? (if relevant)
Not Relevant
Describe the Bug
Summary
When using overlapping catch-all routes, requesting the page by entering the URL directly and by triggering a client-side transition (with <Link> or using router) renders a different page, which is caused by resolving to a different bundle.
Client-side transition resolves to the wrong bundle, while entering the URL directly resolves to the correct one.
As you can see, /[...slug] generates /foo/bar due to its getStaticPaths return value, also, /foo/bar, on the other hand, is not generating any pages due to returning an empty paths array from its getStaticPaths.
Additionally, we also have an index.js file, whose implementation is the following:
// index.js
import Link from "next/link";
export default function Page() {
return <Link href="/foo/bar">Click Me</Link>
}
It merely contains a <Link> that triggers a client-side transition to /foo/bar.
When first navigating using a client-side transition to /foo/bar, we receive the bundle from /foo/[...slug], even though the request is actually resolved to /[...slug], and we can even see that the props that were returned by the AJAX request are the ones that correspond to /[...slug].
When we refresh the page at /foo/bar, then, the bundle is resolved correctly.
When running next dev, we can even see how part of the resolution process is taking place:
On the first request:
Our call to /foo/bar is first handled by /foo/[...slug], due to it being more specific than /[...slug].
Then, as /foo/[...slug]getStaticPaths returns an empty paths array and it has fallback: false, it understands that /foo/[...slug] is not able to handle the request to /foo/bar, so it fallbacks to /[...slug].
When the "request reaches" /[...slug], it first computes its getStaticPaths and then realizes that it is able to handle the request to /foo/bar, and then run its getStaticProps and pass the returned props to Foo.
So, even though the request is handled correctly by the server, the problem is that the bundle that is resolved to by the client side transition, is the one that comes from /foo/[...slug].
Expected Behavior
I'd expect that regardless of using a client side or a server side transition, requests would resolve to the same page/bundle.
Ideally, the client-side transition behavior would match the server-side one.
Verify canary release
Provide environment information
What browser are you using? (if relevant)
Version 103.0.5060.134 (Official Build) (64-bit)
How are you deploying your application? (if relevant)
Not Relevant
Describe the Bug
Summary
When using overlapping catch-all routes, requesting the page by entering the URL directly and by triggering a client-side transition (with
<Link>
or usingrouter
) renders a different page, which is caused by resolving to a different bundle.Client-side transition resolves to the wrong bundle, while entering the URL directly resolves to the correct one.
Probably related to #37686
Setup
Consider the following page structure:
And the following build:
Note that:
/
and another inside/foo
.getStaticPaths
,/[...slug]
is generating/foo/bar
, and/foo/[...slug]
is not generating any pages.Now, let's take a look at these catch all routes implementations:
As you can see,
/[...slug]
generates/foo/bar
due to itsgetStaticPaths
return value, also,/foo/bar
, on the other hand, is not generating any pages due to returning an empty paths array from itsgetStaticPaths
.Additionally, we also have an
index.js
file, whose implementation is the following:It merely contains a
<Link>
that triggers a client-side transition to/foo/bar
.Bug
https://user-images.githubusercontent.com/20905415/180459915-52583b7d-bafa-4c2f-b6ed-78987f8ecd4a.mp4
Notice that:
/foo/bar
, we receive the bundle from/foo/[...slug]
, even though the request is actually resolved to/[...slug]
, and we can even see that the props that were returned by the AJAX request are the ones that correspond to/[...slug]
./foo/bar
, then, the bundle is resolved correctly.When running
next dev
, we can even see how part of the resolution process is taking place:On the first request:
Our call to
/foo/bar
is first handled by/foo/[...slug]
, due to it being more specific than/[...slug]
.Then, as
/foo/[...slug]
getStaticPaths
returns an emptypaths
array and it hasfallback: false
, it understands that/foo/[...slug]
is not able to handle the request to/foo/bar
, so it fallbacks to/[...slug]
.When the "request reaches"
/[...slug]
, it first computes itsgetStaticPaths
and then realizes that it is able to handle the request to/foo/bar
, and then run itsgetStaticProps
and pass the returned props toFoo
.So, even though the request is handled correctly by the server, the problem is that the bundle that is resolved to by the client side transition, is the one that comes from
/foo/[...slug]
.Expected Behavior
I'd expect that regardless of using a client side or a server side transition, requests would resolve to the same page/bundle.
Ideally, the client-side transition behavior would match the server-side one.
Link to reproduction
https://stackblitz.com/edit/vercel-next-js-ok79yz?file=pages%2Ffoo%2F[...slug].js,pages%2F[...slug].js,pages%2Findex.tsx
To Reproduce
/
/foo/[...slug]
4.2. The props that were returned via AJAX come from/[...slug]
/[...slug]