Fix missing .rsc outputs for pages prerenders (#11503)

When generating the outputs for pages when app router is also present we weren't creating the placeholder `.rsc` outputs for all prerender outputs so when a `fallback: false` route was configured in the pages router that could fall through to an app route it causes issues with client-navigation behaving differently than a direct visit. 

This ensures we add the placeholder `.rsc` outputs for all prerenders so that `fallback: false` pages don't have this unexpected behavior.
This commit is contained in:
JJ Kasper
2024-04-30 13:34:41 -07:00
committed by GitHub
parent 303256343a
commit 52e435aa5d
5 changed files with 94 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
---
"@vercel/next": patch
---
Fix missing .rsc outputs for pages prerenders

View File

@@ -2477,6 +2477,22 @@ export const onPrerenderRoute =
}); });
} }
// we need to ensure all prerenders have a matching .rsc output
// otherwise routing could fall through unexpectedly for the
// fallback: false case as it doesn't have a dynamic route
// to catch the `.rsc` request for app -> pages routing
if (outputPrerenderPathData?.endsWith('.json') && appDir) {
const dummyOutput = new FileBlob({
data: '{}',
contentType: 'application/json',
});
const rscKey = `${outputPathPage}.rsc`;
const prefetchRscKey = `${outputPathPage}${RSC_PREFETCH_SUFFIX}`;
prerenders[rscKey] = dummyOutput;
prerenders[prefetchRscKey] = dummyOutput;
}
++prerenderGroup; ++prerenderGroup;
if (routesManifest?.i18n && isBlocking) { if (routesManifest?.i18n && isBlocking) {

View File

@@ -0,0 +1,5 @@
export default function Page() {
return (
<p>nested app router catch-all</p>
)
}

View File

@@ -0,0 +1,24 @@
export default function Page(props) {
return (
<>
<p>hello from /nested/blog-fallback-false/[slug]</p>
</>
);
}
export function getStaticProps() {
return {
props: {
now: Date.now()
}
}
}
export function getStaticPaths() {
return {
paths: [
{ params: { slug: 'first' } },
],
fallback: false
}
}

View File

@@ -18,6 +18,50 @@
} }
], ],
"probes": [ "probes": [
{
"path": "/nested/blog-fallback-false/first",
"status": 200,
"mustContain": "hello from /nested/blog-fallback-false"
},
{
"path": "/nested/blog-fallback-false/first",
"status": 200,
"mustContain": "{}",
"mustNotContain": ":",
"responseHeaders": {
"x-matched-path": "/nested/blog-fallback-false/first.prefetch.rsc"
},
"headers": {
"RSC": 1,
"Next-Router-Prefetch": 1
}
},
{
"path": "/nested/blog-fallback-false/first",
"status": 200,
"mustContain": "{}",
"mustNotContain": ":",
"responseHeaders": {
"x-matched-path": "/nested/blog-fallback-false/first.rsc"
},
"headers": {
"RSC": 1
}
},
{
"path": "/nested/blog-fallback-false/non-existent",
"status": 200,
"mustContain": "nested app router catch-all"
},
{
"path": "/nested/blog-fallback-false/non-existent",
"status": 200,
"mustContain": ":",
"headers": {
"RSC": 1,
"Next-Router-Prefetch": 1
}
},
{ {
"path": "/dynamic-index/hello/index", "path": "/dynamic-index/hello/index",
"status": 200, "status": 200,