mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-10 04:22:12 +00:00
[next] fix content-type for RSC prefetches (#10487)
This ensures that the `.prefetch.rsc` requests respond with the correct `content-type` since this is used by Next.js to determine if a request is valid or not (and in the case it's invalid, an mpa navigation will occur) Fixes: https://github.com/vercel/next.js/issues/54934
This commit is contained in:
5
.changeset/popular-donuts-jump.md
Normal file
5
.changeset/popular-donuts-jump.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@vercel/next": patch
|
||||
---
|
||||
|
||||
fix content-type for RSC prefetches
|
||||
@@ -45,6 +45,8 @@ import {
|
||||
UnwrapPromise,
|
||||
getOperationType,
|
||||
FunctionsConfigManifestV1,
|
||||
RSC_CONTENT_TYPE,
|
||||
RSC_PREFETCH_SUFFIX,
|
||||
} from './utils';
|
||||
import {
|
||||
nodeFileTrace,
|
||||
@@ -168,7 +170,6 @@ export async function serverBuild({
|
||||
}
|
||||
}
|
||||
|
||||
const APP_PREFETCH_SUFFIX = '.prefetch.rsc';
|
||||
let appRscPrefetches: UnwrapPromise<ReturnType<typeof glob>> = {};
|
||||
let appBuildTraces: UnwrapPromise<ReturnType<typeof glob>> = {};
|
||||
let appDir: string | null = null;
|
||||
@@ -176,7 +177,18 @@ export async function serverBuild({
|
||||
if (appPathRoutesManifest) {
|
||||
appDir = path.join(pagesDir, '../app');
|
||||
appBuildTraces = await glob('**/*.js.nft.json', appDir);
|
||||
appRscPrefetches = await glob(`**/*${APP_PREFETCH_SUFFIX}`, appDir);
|
||||
appRscPrefetches = await glob(`**/*${RSC_PREFETCH_SUFFIX}`, appDir);
|
||||
|
||||
const rscContentTypeHeader =
|
||||
routesManifest?.rsc?.contentTypeHeader || RSC_CONTENT_TYPE;
|
||||
|
||||
// ensure all appRscPrefetches have a contentType since this is used by Next.js
|
||||
// to determine if it's a valid response
|
||||
for (const value of Object.values(appRscPrefetches)) {
|
||||
if (!value.contentType) {
|
||||
value.contentType = rscContentTypeHeader;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const isCorrectNotFoundRoutes = semver.gte(
|
||||
@@ -1526,7 +1538,7 @@ export async function serverBuild({
|
||||
dest: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'/index.prefetch.rsc'
|
||||
`/index${RSC_PREFETCH_SUFFIX}`
|
||||
),
|
||||
headers: { vary: rscVaryHeader },
|
||||
continue: true,
|
||||
@@ -1547,7 +1559,7 @@ export async function serverBuild({
|
||||
dest: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
`/$1${APP_PREFETCH_SUFFIX}`
|
||||
`/$1${RSC_PREFETCH_SUFFIX}`
|
||||
),
|
||||
headers: { vary: rscVaryHeader },
|
||||
continue: true,
|
||||
@@ -1626,7 +1638,7 @@ export async function serverBuild({
|
||||
src: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
`/index${APP_PREFETCH_SUFFIX}`
|
||||
`/index${RSC_PREFETCH_SUFFIX}`
|
||||
),
|
||||
dest: path.posix.join('/', entryDirectory, '/index.rsc'),
|
||||
has: [
|
||||
@@ -1642,7 +1654,7 @@ export async function serverBuild({
|
||||
src: `^${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
`/(.+?)${APP_PREFETCH_SUFFIX}(?:/)?$`
|
||||
`/(.+?)${RSC_PREFETCH_SUFFIX}(?:/)?$`
|
||||
)}`,
|
||||
dest: path.posix.join('/', entryDirectory, '/$1.rsc'),
|
||||
has: [
|
||||
|
||||
@@ -48,6 +48,9 @@ export const MIB = 1024 * KIB;
|
||||
|
||||
export const prettyBytes = (n: number) => bytes(n, { unitSeparator: ' ' });
|
||||
|
||||
export const RSC_CONTENT_TYPE = 'x-component';
|
||||
export const RSC_PREFETCH_SUFFIX = '.prefetch.rsc';
|
||||
|
||||
// Identify /[param]/ in route string
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
const TEST_DYNAMIC_ROUTE = /\/\[[^\/]+?\](?=\/|$)/;
|
||||
@@ -2158,7 +2161,7 @@ export const onPrerenderRoute =
|
||||
routesManifest?.rsc?.varyHeader ||
|
||||
'RSC, Next-Router-State-Tree, Next-Router-Prefetch';
|
||||
const rscContentTypeHeader =
|
||||
routesManifest?.rsc?.contentTypeHeader || 'text/x-component';
|
||||
routesManifest?.rsc?.contentTypeHeader || RSC_CONTENT_TYPE;
|
||||
|
||||
let sourcePath: string | undefined;
|
||||
if (`/${outputPathPage}` !== srcRoute && srcRoute) {
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
"RSC": "1",
|
||||
"Next-Router-Prefetch": "1"
|
||||
},
|
||||
"responseHeaders": {
|
||||
"content-type":"text/x-component"
|
||||
},
|
||||
"mustContain": ":",
|
||||
"mustNotContain": "<html"
|
||||
},
|
||||
@@ -72,6 +75,9 @@
|
||||
"headers": {
|
||||
"Next-Router-Prefetch": "1",
|
||||
"RSC": "1"
|
||||
},
|
||||
"responseHeaders": {
|
||||
"content-type":"text/x-component"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -99,7 +105,8 @@
|
||||
"path": "/ssg",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"vary": "RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Url"
|
||||
"vary": "RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Url",
|
||||
"content-type":"text/x-component"
|
||||
},
|
||||
"headers": {
|
||||
"RSC": "1",
|
||||
|
||||
Reference in New Issue
Block a user