Skip to content

Commit 13f0303

Browse files
authored
Reduce FS access for incremental cache (#57902)
This passes down the route kind information to the incrememntal cache so it no longer needs to test some files existing in order to validate if the file exists or not for a route.
1 parent 7b524fa commit 13f0303

File tree

23 files changed

+401
-284
lines changed

23 files changed

+401
-284
lines changed

packages/next/src/build/index.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ import type { BuildManifest } from '../server/get-page-files'
8181
import { normalizePagePath } from '../shared/lib/page-path/normalize-page-path'
8282
import { getPagePath } from '../server/require'
8383
import * as ciEnvironment from '../telemetry/ci-info'
84+
8485
import {
8586
eventBuildOptimize,
8687
eventCliSession,
@@ -155,6 +156,7 @@ import { collectBuildTraces } from './collect-build-traces'
155156
import type { BuildTraceContext } from './webpack/plugins/next-trace-entrypoints-plugin'
156157
import { formatManifest } from './manifests/formatter/format-manifest'
157158
import { getStartServerInfo, logStartInfo } from '../server/lib/app-info-log'
159+
import type { NextEnabledDirectories } from '../server/base-server'
158160

159161
interface ExperimentalBypassForInfo {
160162
experimentalBypassFor?: RouteHas[]
@@ -347,7 +349,6 @@ export default async function build(
347349
const isCompile = buildMode === 'experimental-compile'
348350
const isGenerate = buildMode === 'experimental-generate'
349351

350-
let hasAppDir = false
351352
try {
352353
const nextBuildSpan = trace('next-build', undefined, {
353354
buildMode: buildMode,
@@ -432,11 +433,14 @@ export default async function build(
432433
setGlobal('telemetry', telemetry)
433434

434435
const publicDir = path.join(dir, 'public')
435-
const isAppDirEnabled = true
436436
const { pagesDir, appDir } = findPagesDir(dir)
437437
NextBuildContext.pagesDir = pagesDir
438438
NextBuildContext.appDir = appDir
439-
hasAppDir = Boolean(appDir)
439+
440+
const enabledDirectories: NextEnabledDirectories = {
441+
app: typeof appDir === 'string',
442+
pages: typeof pagesDir === 'string',
443+
}
440444

441445
const isSrcDir = path
442446
.relative(dir, pagesDir || appDir || '')
@@ -1292,8 +1296,9 @@ export default async function build(
12921296
} = await initializeIncrementalCache({
12931297
fs: nodeFs,
12941298
dev: false,
1295-
appDir: isAppDirEnabled,
1296-
fetchCache: isAppDirEnabled,
1299+
pagesDir: true,
1300+
appDir: true,
1301+
fetchCache: true,
12971302
flushToDisk: config.experimental.isrFlushToDisk,
12981303
serverDistDir: path.join(distDir, 'server'),
12991304
fetchCacheKeyPrefix: config.experimental.fetchCacheKeyPrefix,
@@ -1317,7 +1322,7 @@ export default async function build(
13171322
incrementalCacheIpcPort,
13181323
incrementalCacheIpcValidationKey
13191324
)
1320-
const appStaticWorkers = isAppDirEnabled
1325+
const appStaticWorkers = appDir
13211326
? createStaticWorker(
13221327
incrementalCacheIpcPort,
13231328
incrementalCacheIpcValidationKey
@@ -2032,7 +2037,7 @@ export default async function build(
20322037
(combinedPages.length > 0 ||
20332038
useStaticPages404 ||
20342039
useDefaultStatic500 ||
2035-
isAppDirEnabled)
2040+
appDir)
20362041
) {
20372042
const staticGenerationSpan =
20382043
nextBuildSpan.traceChild('static-generation')
@@ -2172,7 +2177,7 @@ export default async function build(
21722177

21732178
const exportOptions: ExportAppOptions = {
21742179
nextConfig: exportConfig,
2175-
hasAppDir,
2180+
enabledDirectories,
21762181
silent: false,
21772182
buildExport: true,
21782183
debugOutput,
@@ -2870,7 +2875,7 @@ export default async function build(
28702875
const options: ExportAppOptions = {
28712876
buildExport: false,
28722877
nextConfig: config,
2873-
hasAppDir,
2878+
enabledDirectories,
28742879
silent: true,
28752880
threads: config.experimental.cpus,
28762881
outdir: path.join(dir, configOutDir),

packages/next/src/build/utils.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ import { nodeFs } from '../server/lib/node-fs-methods'
6969
import * as ciEnvironment from '../telemetry/ci-info'
7070
import { normalizeAppPath } from '../shared/lib/router/utils/app-paths'
7171
import { denormalizeAppPagePath } from '../shared/lib/page-path/denormalize-app-path'
72-
import { AppRouteRouteModule } from '../server/future/route-modules/app-route/module.compiled'
7372
import { RouteKind } from '../server/future/route-kind'
73+
import { isAppRouteRouteModule } from '../server/future/route-modules/checks'
7474

7575
export type ROUTER_TYPE = 'pages' | 'app'
7676

@@ -1267,6 +1267,8 @@ export async function buildAppStaticPaths({
12671267
const incrementalCache = new IncrementalCache({
12681268
fs: nodeFs,
12691269
dev: true,
1270+
// Enabled both for build as we're only writing this cache, not reading it.
1271+
pagesDir: true,
12701272
appDir: true,
12711273
flushToDisk: isrFlushToDisk,
12721274
serverDistDir: path.join(distDir, 'server'),
@@ -1506,7 +1508,7 @@ export async function isPageStatic({
15061508
const { tree, staticGenerationAsyncStorage, serverHooks } = ComponentMod
15071509

15081510
const generateParams: GenerateParams =
1509-
routeModule && AppRouteRouteModule.is(routeModule)
1511+
routeModule && isAppRouteRouteModule(routeModule)
15101512
? [
15111513
{
15121514
config: {

packages/next/src/export/helpers/create-incremental-cache.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1+
import type { NextEnabledDirectories } from '../../server/base-server'
2+
13
import path from 'path'
2-
import fs from 'fs'
34
import { IncrementalCache } from '../../server/lib/incremental-cache'
45
import { hasNextSupport } from '../../telemetry/ci-info'
6+
import { nodeFs } from '../../server/lib/node-fs-methods'
57

68
export function createIncrementalCache(
79
incrementalCacheHandlerPath: string | undefined,
810
isrMemoryCacheSize: number | undefined,
911
fetchCacheKeyPrefix: string | undefined,
1012
distDir: string,
11-
dir: string
13+
dir: string,
14+
enabledDirectories: NextEnabledDirectories
1215
) {
1316
// Custom cache handler overrides.
1417
let CacheHandler: any
@@ -37,13 +40,9 @@ export function createIncrementalCache(
3740
},
3841
notFoundRoutes: [],
3942
}),
40-
fs: {
41-
readFile: fs.promises.readFile,
42-
readFileSync: fs.readFileSync,
43-
writeFile: (f, d) => fs.promises.writeFile(f, d),
44-
mkdir: (d) => fs.promises.mkdir(d, { recursive: true }),
45-
stat: (f) => fs.promises.stat(f),
46-
},
43+
fs: nodeFs,
44+
pagesDir: enabledDirectories.pages,
45+
appDir: enabledDirectories.app,
4746
serverDistDir: path.join(distDir, 'server'),
4847
CurCacheHandler: CacheHandler,
4948
minimalMode: hasNextSupport,

packages/next/src/export/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ export async function exportAppImpl(
215215
// attempt to load global env values so they are available in next.config.js
216216
span.traceChild('load-dotenv').traceFn(() => loadEnvConfig(dir, false, Log))
217217

218+
const { enabledDirectories } = options
219+
218220
const nextConfig =
219221
options.nextConfig ||
220222
(await span
@@ -444,7 +446,7 @@ export async function exportAppImpl(
444446
}
445447

446448
let serverActionsManifest
447-
if (options.hasAppDir) {
449+
if (enabledDirectories.app) {
448450
serverActionsManifest = require(join(
449451
distDir,
450452
SERVER_DIRECTORY,
@@ -487,15 +489,15 @@ export async function exportAppImpl(
487489
nextScriptWorkers: nextConfig.experimental.nextScriptWorkers,
488490
optimizeFonts: nextConfig.optimizeFonts as FontConfig,
489491
largePageDataBytes: nextConfig.experimental.largePageDataBytes,
490-
serverComponents: options.hasAppDir,
491492
serverActions: nextConfig.experimental.serverActions,
493+
serverComponents: enabledDirectories.app,
492494
nextFontManifest: require(join(
493495
distDir,
494496
'server',
495497
`${NEXT_FONT_MANIFEST}.json`
496498
)),
497499
images: nextConfig.images,
498-
...(options.hasAppDir
500+
...(enabledDirectories.app
499501
? {
500502
serverActionsManifest,
501503
}
@@ -698,6 +700,7 @@ export async function exportAppImpl(
698700
incrementalCacheHandlerPath:
699701
nextConfig.experimental.incrementalCacheHandlerPath,
700702
enableExperimentalReact: needsExperimentalReact(nextConfig),
703+
enabledDirectories,
701704
})
702705
})
703706

packages/next/src/export/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type { FontConfig } from '../server/font-utils'
88
import type { ExportPathMap, NextConfigComplete } from '../server/config-shared'
99
import type { Span } from '../trace'
1010
import type { Revalidate } from '../server/lib/revalidate'
11+
import type { NextEnabledDirectories } from '../server/base-server'
1112

1213
export interface AmpValidation {
1314
page: string
@@ -58,6 +59,7 @@ export interface ExportPageInput {
5859
fetchCacheKeyPrefix?: string
5960
nextConfigOutput?: NextConfigComplete['output']
6061
enableExperimentalReact?: boolean
62+
enabledDirectories: NextEnabledDirectories
6163
}
6264

6365
export type ExportedPageFile = {
@@ -98,7 +100,7 @@ export type ExportWorker = (
98100

99101
export interface ExportAppOptions {
100102
outdir: string
101-
hasAppDir: boolean
103+
enabledDirectories: NextEnabledDirectories
102104
silent?: boolean
103105
threads?: number
104106
debugOutput?: boolean

packages/next/src/export/worker.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ async function exportPageImpl(
6565
enableExperimentalReact,
6666
ampValidatorPath,
6767
trailingSlash,
68+
enabledDirectories,
6869
} = input
6970

7071
if (enableExperimentalReact) {
@@ -222,7 +223,8 @@ async function exportPageImpl(
222223
isrMemoryCacheSize,
223224
fetchCacheKeyPrefix,
224225
distDir,
225-
dir
226+
dir,
227+
enabledDirectories
226228
)
227229
: undefined
228230

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type { IncomingHttpHeaders } from 'node:http'
2+
3+
import { FLIGHT_PARAMETERS } from '../../client/components/app-router-headers'
4+
5+
/**
6+
* Removes the flight headers from the request.
7+
*
8+
* @param req the request to strip the headers from
9+
*/
10+
export function stripFlightHeaders(headers: IncomingHttpHeaders) {
11+
for (const [header] of FLIGHT_PARAMETERS) {
12+
delete headers[header.toLowerCase()]
13+
}
14+
}

0 commit comments

Comments
 (0)