Skip to content

Commit

Permalink
Add handling to leverage RSC prefetch outputs (#10390)
Browse files Browse the repository at this point in the history
Implements handling for the RSC prefetch outputs when available that
were added in vercel/next.js#54403
  • Loading branch information
ijjk committed Aug 24, 2023
1 parent 09446a8 commit 4422326
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/slimy-comics-serve.md
@@ -0,0 +1,5 @@
---
"@vercel/next": patch
---

Add handling to leverage RSC prefetch outputs
103 changes: 101 additions & 2 deletions packages/next/src/server-build.ts
Expand Up @@ -168,12 +168,15 @@ 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;

if (appPathRoutesManifest) {
appDir = path.join(pagesDir, '../app');
appBuildTraces = await glob('**/*.js.nft.json', appDir);
appRscPrefetches = await glob(`**/*${APP_PREFETCH_SUFFIX}`, appDir);
}

const isCorrectNotFoundRoutes = semver.gte(
Expand Down Expand Up @@ -1225,6 +1228,7 @@ export async function serverBuild({
}

const rscHeader = routesManifest.rsc?.header?.toLowerCase() || '__rsc__';
const rscPrefetchHeader = routesManifest.rsc?.prefetchHeader?.toLowerCase();
const rscVaryHeader =
routesManifest?.rsc?.varyHeader ||
'RSC, Next-Router-State-Tree, Next-Router-Prefetch';
Expand All @@ -1236,6 +1240,7 @@ export async function serverBuild({
output: {
...publicDirectoryFiles,
...lambdas,
...appRscPrefetches,
// Prerenders may override Lambdas -- this is an intentional behavior.
...prerenders,
...staticPages,
Expand Down Expand Up @@ -1475,6 +1480,49 @@ export async function serverBuild({

...(appDir
? [
...(rscPrefetchHeader
? [
{
src: `^${path.posix.join('/', entryDirectory, '/')}`,
has: [
{
type: 'header',
key: rscPrefetchHeader,
},
],
dest: path.posix.join(
'/',
entryDirectory,
'/index.prefetch.rsc'
),
headers: { vary: rscVaryHeader },
continue: true,
override: true,
},
{
src: `^${path.posix.join(
'/',
entryDirectory,
'/((?!.+\\.rsc).+?)(?:/)?$'
)}`,
has: [
{
type: 'header',
key: rscPrefetchHeader,
},
],
dest: path.posix.join(
'/',
entryDirectory,
`/$1${APP_PREFETCH_SUFFIX}`
),
headers: { vary: rscVaryHeader },
continue: true,
override: true,
},
]
: []),

{
src: `^${path.posix.join('/', entryDirectory, '/')}`,
has: [
Expand Down Expand Up @@ -1539,6 +1587,43 @@ export async function serverBuild({
]
: []),

...(rscPrefetchHeader
? [
{
src: path.posix.join(
'/',
entryDirectory,
`/index${APP_PREFETCH_SUFFIX}`
),
dest: path.posix.join('/', entryDirectory, '/index.rsc'),
has: [
{
type: 'header',
key: rscPrefetchHeader,
},
],
continue: true,
override: true,
},
{
src: `^${path.posix.join(
'/',
entryDirectory,
`/(.+?)${APP_PREFETCH_SUFFIX}(?:/)?$`
)}`,
dest: path.posix.join('/', entryDirectory, '/$1.rsc'),
has: [
{
type: 'header',
key: rscPrefetchHeader,
},
],
continue: true,
override: true,
},
]
: []),

...(appDir
? [
// check routes that end in `.rsc` to see if a page with the resulting name (sans-.rsc) exists in the filesystem
Expand All @@ -1552,8 +1637,18 @@ export async function serverBuild({
key: rscHeader,
},
],
...(rscPrefetchHeader
? {
missing: [
{
type: 'header',
key: rscPrefetchHeader,
},
],
}
: {}),
check: true,
},
} as Route,
]
: []),

Expand All @@ -1565,7 +1660,11 @@ export async function serverBuild({
? [
// rewrite route back to `.rsc`, but skip checking fs
{
src: `^${path.posix.join('/', entryDirectory, '/(.*)$')}`,
src: `^${path.posix.join(
'/',
entryDirectory,
'/((?!.+\\.rsc).+?)(?:/)?$'
)}`,
has: [
{
type: 'header',
Expand Down
1 change: 1 addition & 0 deletions packages/next/src/utils.ts
Expand Up @@ -236,6 +236,7 @@ type RoutesManifestOld = {
rsc?: {
header: string;
varyHeader: string;
prefetchHeader?: string;
contentTypeHeader: string;
};
skipMiddlewareUrlNormalize?: boolean;
Expand Down
@@ -1,3 +1,5 @@
export const dynamic = 'force-dynamic'

export default function ClientPage() {
return (
<>
Expand Down
42 changes: 42 additions & 0 deletions packages/next/test/fixtures/00-app-dir/vercel.json
Expand Up @@ -37,6 +37,16 @@
"mustContain": ":{",
"mustNotContain": "<html"
},
{
"path": "/dynamic/category-1/id-1",
"status": 200,
"headers": {
"RSC": "1",
"Next-Router-Prefetch": "1"
},
"mustContain": ":",
"mustNotContain": "<html"
},
{
"path": "/ssg",
"status": 200,
Expand All @@ -45,6 +55,25 @@
"vary": "RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Url"
}
},
{
"path": "/client-nested",
"status": 200,
"mustContain": ":",
"mustNotContain": "<html",
"headers": {
"Next-Router-Prefetch": "1",
"RSC": "1"
}
},
{
"path": "/client-nested",
"status": 200,
"mustContain": "hello",
"mustNotContain": "<html",
"headers": {
"RSC": "1"
}
},
{
"path": "/ssg",
"status": 200,
Expand All @@ -57,6 +86,19 @@
"mustContain": ":{",
"mustNotContain": "<html"
},
{
"path": "/ssg",
"status": 200,
"responseHeaders": {
"vary": "RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Url"
},
"headers": {
"RSC": "1",
"Next-Router-Prefetch": "1"
},
"mustContain": ":{",
"mustNotContain": "<html"
},
{
"path": "/ssg?override=1",
"status": 307,
Expand Down

0 comments on commit 4422326

Please sign in to comment.