From eb65ed37b02c19514f98047a5958c5f895016b39 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Fri, 3 Dec 2021 01:47:16 +0100 Subject: [PATCH] avoid retaining webpack config too long (#32053) avoids keeping the webpack compiler during after webpack build build steps like SSG etc. (review with ignore whitespace) ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `yarn lint` --- packages/next/build/index.ts | 186 ++++++++++++++++++----------------- 1 file changed, 95 insertions(+), 91 deletions(-) diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts index ea7417caae824..777bb5de0ae23 100644 --- a/packages/next/build/index.ts +++ b/packages/next/build/index.ts @@ -571,105 +571,112 @@ export default async function build( ignore: [] as string[], })) - const runWebpackSpan = nextBuildSpan.traceChild('run-webpack-compiler') - const configs = await runWebpackSpan - .traceChild('generate-webpack-config') - .traceAsyncFn(() => - Promise.all([ - getBaseWebpackConfig(dir, { - buildId, - reactProductionProfiling, - isServer: false, - config, - target, - pagesDir, - entrypoints: entrypoints.client, - rewrites, - runWebpackSpan, - }), - getBaseWebpackConfig(dir, { - buildId, - reactProductionProfiling, - isServer: true, - config, - target, - pagesDir, - entrypoints: entrypoints.server, - rewrites, - runWebpackSpan, - }), - hasConcurrentFeatures - ? getBaseWebpackConfig(dir, { - buildId, - reactProductionProfiling, - isServer: true, - webServerRuntime: true, - config, - target, - pagesDir, - entrypoints: entrypoints.serverWeb, - rewrites, - runWebpackSpan, - }) - : null, - ]) - ) + let result: CompilerResult = { warnings: [], errors: [] } + let webpackBuildStart + let telemetryPlugin + await (async () => { + // IIFE to isolate locals and avoid retaining memory too long + const runWebpackSpan = nextBuildSpan.traceChild('run-webpack-compiler') + const configs = await runWebpackSpan + .traceChild('generate-webpack-config') + .traceAsyncFn(() => + Promise.all([ + getBaseWebpackConfig(dir, { + buildId, + reactProductionProfiling, + isServer: false, + config, + target, + pagesDir, + entrypoints: entrypoints.client, + rewrites, + runWebpackSpan, + }), + getBaseWebpackConfig(dir, { + buildId, + reactProductionProfiling, + isServer: true, + config, + target, + pagesDir, + entrypoints: entrypoints.server, + rewrites, + runWebpackSpan, + }), + hasConcurrentFeatures + ? getBaseWebpackConfig(dir, { + buildId, + reactProductionProfiling, + isServer: true, + webServerRuntime: true, + config, + target, + pagesDir, + entrypoints: entrypoints.serverWeb, + rewrites, + runWebpackSpan, + }) + : null, + ]) + ) - const clientConfig = configs[0] + const clientConfig = configs[0] - if ( - clientConfig.optimization && - (clientConfig.optimization.minimize !== true || - (clientConfig.optimization.minimizer && - clientConfig.optimization.minimizer.length === 0)) - ) { - Log.warn( - `Production code optimization has been disabled in your project. Read more: https://nextjs.org/docs/messages/minification-disabled` - ) - } + if ( + clientConfig.optimization && + (clientConfig.optimization.minimize !== true || + (clientConfig.optimization.minimizer && + clientConfig.optimization.minimizer.length === 0)) + ) { + Log.warn( + `Production code optimization has been disabled in your project. Read more: https://nextjs.org/docs/messages/minification-disabled` + ) + } - const webpackBuildStart = process.hrtime() + webpackBuildStart = process.hrtime() - 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, { runWebpackSpan }) - // Fail build if clientResult contains errors - if (clientResult.errors.length > 0) { - result = { - warnings: [...clientResult.warnings], - errors: [...clientResult.errors], - } - } else { - const serverResult = await runCompiler(configs[1], { runWebpackSpan }) - const serverWebResult = configs[2] - ? await runCompiler(configs[2], { runWebpackSpan }) - : null - - result = { - warnings: [ - ...clientResult.warnings, - ...serverResult.warnings, - ...(serverWebResult?.warnings || []), - ], - errors: [ - ...clientResult.errors, - ...serverResult.errors, - ...(serverWebResult?.errors || []), - ], + // We run client and server compilation separately to optimize for memory usage + await runWebpackSpan.traceAsyncFn(async () => { + const clientResult = await runCompiler(clientConfig, { runWebpackSpan }) + // Fail build if clientResult contains errors + if (clientResult.errors.length > 0) { + result = { + warnings: [...clientResult.warnings], + errors: [...clientResult.errors], + } + } else { + const serverResult = await runCompiler(configs[1], { runWebpackSpan }) + const serverWebResult = configs[2] + ? await runCompiler(configs[2], { runWebpackSpan }) + : null + + result = { + warnings: [ + ...clientResult.warnings, + ...serverResult.warnings, + ...(serverWebResult?.warnings || []), + ], + errors: [ + ...clientResult.errors, + ...serverResult.errors, + ...(serverWebResult?.errors || []), + ], + } } - } - }) + }) + result = nextBuildSpan + .traceChild('format-webpack-messages') + .traceFn(() => formatWebpackMessages(result, true)) + telemetryPlugin = (clientConfig as webpack.Configuration).plugins?.find( + isTelemetryPlugin + ) + })() const webpackBuildEnd = process.hrtime(webpackBuildStart) if (buildSpinner) { buildSpinner.stopAndPersist() } - result = nextBuildSpan - .traceChild('format-webpack-messages') - .traceFn(() => formatWebpackMessages(result, true)) - if (result.errors.length > 0) { // Only keep the first few errors. Others are often indicative // of the same problem, but confuse the reader with noise. @@ -1871,9 +1878,6 @@ export default async function build( }) ) - const telemetryPlugin = ( - clientConfig as webpack.Configuration - ).plugins?.find(isTelemetryPlugin) if (telemetryPlugin) { const events = eventBuildFeatureUsage(telemetryPlugin) telemetry.record(events)