Skip to content

Commit 24b09ad

Browse files
authored
Add entrypoint tracing (#25538)
This adds tracing entrypoints directly after they have have been transpiled to allow us to trace before the webpack runtime has been added to the modules. This should allow for more accurate tracing of entrypoints and allow the trace step to be cached. ## Bug - [x] Related issues linked using `fixes #number` - [x] Integration tests added x-ref: #24700 x-ref: #26200 x-ref: #23894 x-ref: #25431
1 parent da4d652 commit 24b09ad

File tree

27 files changed

+64556
-63847
lines changed

27 files changed

+64556
-63847
lines changed

packages/next/build/index.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,8 @@ export default async function build(
660660
const serverPropsPages = new Set<string>()
661661
const additionalSsgPaths = new Map<string, Array<string>>()
662662
const additionalSsgPathsEncoded = new Map<string, Array<string>>()
663+
const pageTraceIncludes = new Map<string, Array<string>>()
664+
const pageTraceExcludes = new Map<string, Array<string>>()
663665
const pageInfos = new Map<string, PageInfo>()
664666
const pagesManifest = JSON.parse(
665667
await promises.readFile(manifestPath, 'utf8')
@@ -841,6 +843,11 @@ export default async function build(
841843
)
842844
})
843845

846+
if (config.experimental.nftTracing) {
847+
pageTraceIncludes.set(page, workerResult.traceIncludes || [])
848+
pageTraceExcludes.set(page, workerResult.traceExcludes || [])
849+
}
850+
844851
if (
845852
workerResult.isStatic === false &&
846853
(workerResult.isHybridAmp || workerResult.isAmpOnly)
@@ -979,6 +986,63 @@ export default async function build(
979986
)
980987
}
981988

989+
if (config.experimental.nftTracing) {
990+
const globOrig = require('next/dist/compiled/glob') as typeof import('next/dist/compiled/glob')
991+
const glob = (pattern: string): Promise<string[]> => {
992+
return new Promise((resolve, reject) => {
993+
globOrig(pattern, { cwd: dir }, (err, files) => {
994+
if (err) {
995+
return reject(err)
996+
}
997+
resolve(files)
998+
})
999+
})
1000+
}
1001+
1002+
for (const page of pageKeys) {
1003+
const includeGlobs = pageTraceIncludes.get(page)
1004+
const excludeGlobs = pageTraceExcludes.get(page)
1005+
1006+
if (!includeGlobs?.length && !excludeGlobs?.length) {
1007+
continue
1008+
}
1009+
1010+
const traceFile = path.join(
1011+
distDir,
1012+
'server/pages',
1013+
`${page}.js.nft.json`
1014+
)
1015+
const traceContent = JSON.parse(
1016+
await promises.readFile(traceFile, 'utf8')
1017+
)
1018+
let includes: string[] = []
1019+
let excludes: string[] = []
1020+
1021+
if (includeGlobs?.length) {
1022+
for (const includeGlob of includeGlobs) {
1023+
includes.push(...(await glob(includeGlob)))
1024+
}
1025+
}
1026+
1027+
if (excludeGlobs?.length) {
1028+
for (const excludeGlob of excludeGlobs) {
1029+
excludes.push(...(await glob(excludeGlob)))
1030+
}
1031+
}
1032+
1033+
const combined = new Set([...traceContent.files, ...includes])
1034+
excludes.forEach((file) => combined.delete(file))
1035+
1036+
await promises.writeFile(
1037+
traceFile,
1038+
JSON.stringify({
1039+
version: traceContent.version,
1040+
files: [...combined],
1041+
})
1042+
)
1043+
}
1044+
}
1045+
9821046
if (serverPropsPages.size > 0 || ssgPages.size > 0) {
9831047
// We update the routes manifest after the build with the
9841048
// data routes since we can't determine these until after build

packages/next/build/utils.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { getRouteMatcher, getRouteRegex } from '../shared/lib/router/utils'
2323
import { isDynamicRoute } from '../shared/lib/router/utils/is-dynamic'
2424
import escapePathDelimiters from '../shared/lib/router/utils/escape-path-delimiters'
2525
import { findPageFile } from '../server/lib/find-page-file'
26-
import { GetStaticPaths } from 'next/types'
26+
import { GetStaticPaths, PageConfig } from 'next/types'
2727
import { denormalizePagePath } from '../server/normalize-page-path'
2828
import { BuildManifest } from '../server/get-page-files'
2929
import { removePathTrailingSlash } from '../client/normalize-trailing-slash'
@@ -831,6 +831,8 @@ export async function isPageStatic(
831831
encodedPrerenderRoutes?: string[]
832832
prerenderFallback?: boolean | 'blocking'
833833
isNextImageImported?: boolean
834+
traceIncludes?: string[]
835+
traceExcludes?: string[]
834836
}> {
835837
const isPageStaticSpan = trace('is-page-static-utils', parentId)
836838
return isPageStaticSpan.traceAsyncFn(async () => {
@@ -925,7 +927,7 @@ export async function isPageStatic(
925927
}
926928

927929
const isNextImageImported = (global as any).__NEXT_IMAGE_IMPORTED
928-
const config = mod.config || {}
930+
const config: PageConfig = mod.config || {}
929931
return {
930932
isStatic: !hasStaticProps && !hasGetInitialProps && !hasServerProps,
931933
isHybridAmp: config.amp === 'hybrid',
@@ -936,6 +938,8 @@ export async function isPageStatic(
936938
hasStaticProps,
937939
hasServerProps,
938940
isNextImageImported,
941+
traceIncludes: config.unstable_includeFiles || [],
942+
traceExcludes: config.unstable_excludeFiles || [],
939943
}
940944
} catch (err) {
941945
if (err.code === 'MODULE_NOT_FOUND') return {}

packages/next/build/webpack-config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import BuildStatsPlugin from './webpack/plugins/build-stats-plugin'
3838
import ChunkNamesPlugin from './webpack/plugins/chunk-names-plugin'
3939
import { JsConfigPathsPlugin } from './webpack/plugins/jsconfig-paths-plugin'
4040
import { DropClientPage } from './webpack/plugins/next-drop-client-page-plugin'
41+
import { TraceEntryPointsPlugin } from './webpack/plugins/next-trace-entrypoints-plugin'
4142
import NextJsSsrImportPlugin from './webpack/plugins/nextjs-ssr-import'
4243
import NextJsSSRModuleCachePlugin from './webpack/plugins/nextjs-ssr-module-cache'
4344
import PagesManifestPlugin from './webpack/plugins/pages-manifest-plugin'
@@ -1245,6 +1246,12 @@ export default async function getBaseWebpackConfig(
12451246
pagesDir,
12461247
}),
12471248
!isServer && new DropClientPage(),
1249+
config.experimental.nftTracing &&
1250+
!isLikeServerless &&
1251+
isServer &&
1252+
!dev &&
1253+
isWebpack5 &&
1254+
new TraceEntryPointsPlugin({ appDir: dir }),
12481255
// Moment.js is an extremely popular library that bundles large locale files
12491256
// by default due to how Webpack interprets its code. This is a practical
12501257
// solution that requires the user to opt into importing specific locales.

0 commit comments

Comments
 (0)