From 505640dc312347b35b0d17a93ca9ffd83567128b Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 17 Aug 2021 12:20:16 +0200 Subject: [PATCH 1/4] Add relationship between issuer and module to traces Sets the parent span for module traces to the module that caused this current module to compile, this makes tracing why a module was compiled much simpler. Also added `NEXT_WEBPACK_PARALLELISM` to allow for better traces of individual modules, this should only be used in combination with tracing. --- packages/next/build/webpack-config.ts | 1 + packages/next/build/webpack/plugins/profiling-plugin.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 4e85f9b13df83bb..b0fb1a7cc9be6a6 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -860,6 +860,7 @@ export default async function getBaseWebpackConfig( const emacsLockfilePattern = '**/.#*' let webpackConfig: webpack.Configuration = { + parallelism: Number(process.env.NEXT_WEBPACK_PARALLELISM) || undefined, externals: !isServer ? // make sure importing "next" is handled gracefully for client // bundles in case a user imported types and it wasn't removed diff --git a/packages/next/build/webpack/plugins/profiling-plugin.ts b/packages/next/build/webpack/plugins/profiling-plugin.ts index 7de73f69fa74a52..5ce8cc53a0a1a40 100644 --- a/packages/next/build/webpack/plugins/profiling-plugin.ts +++ b/packages/next/build/webpack/plugins/profiling-plugin.ts @@ -101,9 +101,11 @@ export class ProfilingPlugin { return module.userRequest.split('.').pop() })() + const issuerModule = compilation.moduleGraph.getIssuer(module) + const span = trace( `build-module${moduleType ? `-${moduleType}` : ''}`, - compilerSpan.id + issuerModule ? spans.get(issuerModule)?.id : compilerSpan.id ) span.setAttribute('name', module.userRequest) spans.set(module, span) From f8954cff00f8f12addf53a1c336a5dfbde7b6e5c Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 17 Aug 2021 15:39:20 +0200 Subject: [PATCH 2/4] Only load ProfilingPlugin when TRACE_TARGET is set --- packages/next/build/webpack-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index b0fb1a7cc9be6a6..9175e099e3a8924 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1310,7 +1310,7 @@ export default async function getBaseWebpackConfig( new BuildStatsPlugin({ distDir, }), - new ProfilingPlugin({ runWebpackSpan }), + process.env.TRACE_TARGET && new ProfilingPlugin({ runWebpackSpan }), config.optimizeFonts && !dev && isServer && From 74856ea75423db5756b300fa4f2a68b3f7ba5de0 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 17 Aug 2021 17:28:08 +0200 Subject: [PATCH 3/4] Only pass issuerModule when it's available --- packages/next/build/webpack-config.ts | 2 +- packages/next/build/webpack/plugins/profiling-plugin.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 9175e099e3a8924..b0fb1a7cc9be6a6 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1310,7 +1310,7 @@ export default async function getBaseWebpackConfig( new BuildStatsPlugin({ distDir, }), - process.env.TRACE_TARGET && new ProfilingPlugin({ runWebpackSpan }), + new ProfilingPlugin({ runWebpackSpan }), config.optimizeFonts && !dev && isServer && diff --git a/packages/next/build/webpack/plugins/profiling-plugin.ts b/packages/next/build/webpack/plugins/profiling-plugin.ts index 5ce8cc53a0a1a40..e8c131da0329daa 100644 --- a/packages/next/build/webpack/plugins/profiling-plugin.ts +++ b/packages/next/build/webpack/plugins/profiling-plugin.ts @@ -101,7 +101,7 @@ export class ProfilingPlugin { return module.userRequest.split('.').pop() })() - const issuerModule = compilation.moduleGraph.getIssuer(module) + const issuerModule = compilation?.moduleGraph?.getIssuer(module) const span = trace( `build-module${moduleType ? `-${moduleType}` : ''}`, From a279dc9e8e8f78cfbc80ee162a6e5869535800b3 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 17 Aug 2021 18:11:26 +0200 Subject: [PATCH 4/4] Add webpack-close span --- packages/next/build/compiler.ts | 33 ++++++++++++--------------------- packages/next/build/index.ts | 4 ++-- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/packages/next/build/compiler.ts b/packages/next/build/compiler.ts index 6fbf3cfa0af202b..6dff1dc10a01c76 100644 --- a/packages/next/build/compiler.ts +++ b/packages/next/build/compiler.ts @@ -1,4 +1,5 @@ import { webpack } from 'next/dist/compiled/webpack/webpack' +import { Span } from '../telemetry/trace' export type CompilerResult = { errors: string[] @@ -35,16 +36,16 @@ function closeCompiler(compiler: webpack.Compiler | webpack.MultiCompiler) { } export function runCompiler( - config: webpack.Configuration | webpack.Configuration[] + config: webpack.Configuration, + { runWebpackSpan }: { runWebpackSpan: Span } ): Promise { return new Promise((resolve, reject) => { const compiler = webpack(config) - compiler.run( - ( - err: Error, - statsOrMultiStats: { stats: webpack.Stats[] } | webpack.Stats - ) => { - closeCompiler(compiler).then(() => { + compiler.run((err: Error, stats: webpack.Stats) => { + const webpackCloseSpan = runWebpackSpan.traceChild('webpack-close') + webpackCloseSpan + .traceAsyncFn(() => closeCompiler(compiler)) + .then(() => { if (err) { const reason = err?.toString() if (reason) { @@ -53,21 +54,11 @@ export function runCompiler( return reject(err) } - if ('stats' in statsOrMultiStats) { - const result: CompilerResult = statsOrMultiStats.stats.reduce( - generateStats, - { errors: [], warnings: [] } - ) - return resolve(result) - } - - const result = generateStats( - { errors: [], warnings: [] }, - statsOrMultiStats - ) + const result = webpackCloseSpan + .traceChild('webpack-generate-error-stats') + .traceFn(() => generateStats({ errors: [], warnings: [] }, stats)) return resolve(result) }) - } - ) + }) }) } diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts index 2b2db8bf56af53d..294bdcf1e621e65 100644 --- a/packages/next/build/index.ts +++ b/packages/next/build/index.ts @@ -570,7 +570,7 @@ export default async function build( let result: CompilerResult = { warnings: [], errors: [] } // We run client and server compilation separately to optimize for memory usage await runWebpackSpan.traceAsyncFn(async () => { - const clientResult = await runCompiler(clientConfig) + const clientResult = await runCompiler(clientConfig, { runWebpackSpan }) // Fail build if clientResult contains errors if (clientResult.errors.length > 0) { result = { @@ -578,7 +578,7 @@ export default async function build( errors: [...clientResult.errors], } } else { - const serverResult = await runCompiler(configs[1]) + const serverResult = await runCompiler(configs[1], { runWebpackSpan }) result = { warnings: [...clientResult.warnings, ...serverResult.warnings], errors: [...clientResult.errors, ...serverResult.errors],