Skip to content

Commit

Permalink
[next] Preload common chunks (#11126)
Browse files Browse the repository at this point in the history
This PR adds requiring the modules that _we know_ will be required in
the Next.js Lambda in the module scope in a attempt to make a better use
of resources.

---------

Co-authored-by: JJ Kasper <[email protected]>
  • Loading branch information
javivelasco and ijjk authored Feb 6, 2024
1 parent ab24444 commit d21bb9f
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/lazy-trees-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vercel/next': patch
---

Load common chunks on module initialization
75 changes: 74 additions & 1 deletion packages/next/src/server-build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,30 @@ const NEXT_DATA_MIDDLEWARE_RESOLVING_VERSION = 'v12.1.7-canary.33';
const EMPTY_ALLOW_QUERY_FOR_PRERENDERED_VERSION = 'v12.2.0';
const CORRECTED_MANIFESTS_VERSION = 'v12.2.0';

// Ideally this should be in a Next.js manifest so we can change it in
// the future but this also allows us to improve existing versions
const PRELOAD_CHUNKS = {
APP_ROUTER_PAGES: [
'.next/server/webpack-runtime.js',
'next/dist/client/components/action-async-storage.external.js',
'next/dist/client/components/request-async-storage.external.js',
'next/dist/client/components/static-generation-async-storage.external.js',
'next/dist/compiled/next-server/app-page.runtime.prod.js',
],
APP_ROUTER_HANDLER: [
'.next/server/webpack-runtime.js',
'next/dist/compiled/next-server/app-route.runtime.prod.js',
],
PAGES_ROUTER_PAGES: [
'.next/server/webpack-runtime.js',
'next/dist/compiled/next-server/pages.runtime.prod.js',
],
PAGES_ROUTER_API: [
'.next/server/webpack-api-runtime.js',
'next/dist/compiled/next-server/pages-api.runtime.prod.js',
],
};

// related PR: https://github.com/vercel/next.js/pull/52997
// and https://github.com/vercel/next.js/pull/56318
const BUNDLED_SERVER_NEXT_VERSION = 'v13.5.4';
Expand Down Expand Up @@ -1068,9 +1092,58 @@ export async function serverBuild({
}
}

let launcherData = group.isAppRouter ? appLauncher : launcher;
let preloadChunks: string[] = [];

if (process.env.VERCEL_NEXT_PRELOAD_COMMON === '1') {
const nextPackageDir = path.dirname(
resolveFrom(projectDir, 'next/package.json')
);

if (group.isPages) {
preloadChunks = PRELOAD_CHUNKS.PAGES_ROUTER_PAGES;
} else if (group.isApiLambda) {
preloadChunks = PRELOAD_CHUNKS.PAGES_ROUTER_API;
} else if (group.isAppRouter && !group.isAppRouteHandler) {
preloadChunks = PRELOAD_CHUNKS.APP_ROUTER_PAGES;
} else if (group.isAppRouteHandler) {
preloadChunks = PRELOAD_CHUNKS.APP_ROUTER_HANDLER;
}
const normalizedPreloadChunks: string[] = [];

for (const preloadChunk of preloadChunks) {
const absoluteChunk = preloadChunk.startsWith('.next')
? path.join(projectDir, preloadChunk)
: path.join(nextPackageDir, '..', preloadChunk);

// ensure the chunks are actually in this layer
if (
group.pseudoLayer[
path.join('.', path.relative(baseDir, absoluteChunk))
]
) {
normalizedPreloadChunks.push(
// relative files need to be prefixed with ./ for require
preloadChunk.startsWith('.next')
? `./${preloadChunk}`
: preloadChunk
);
}
}

if (normalizedPreloadChunks.length > 0) {
launcherData = launcherData.replace(
'// @preserve next-server-preload-target',
normalizedPreloadChunks
.map(name => `require('${name}');`)
.join('\n')
);
}
}

const launcherFiles: { [name: string]: FileFsRef | FileBlob } = {
[path.join(path.relative(baseDir, projectDir), '___next_launcher.cjs')]:
new FileBlob({ data: group.isAppRouter ? appLauncher : launcher }),
new FileBlob({ data: launcherData }),
};
const operationType = getOperationType({ group, prerenderManifest });

Expand Down
2 changes: 2 additions & 0 deletions packages/next/src/server-launcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ if (process.env.NODE_ENV !== 'production' && region !== 'dev1') {
// eslint-disable-next-line
const NextServer = require('__NEXT_SERVER_PATH__').default;

// @preserve next-server-preload-target

// __NEXT_CONFIG__ value is injected
declare const __NEXT_CONFIG__: any;
const conf = __NEXT_CONFIG__;
Expand Down

0 comments on commit d21bb9f

Please sign in to comment.