diff --git a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md index 1c0aa630495a0..7c8f74d2906fe 100644 --- a/packages/dependency-extraction-webpack-plugin/CHANGELOG.md +++ b/packages/dependency-extraction-webpack-plugin/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Detection of magic comments is now done before minification ([#65582](https://github.com/WordPress/gutenberg/pull/65582)). + ### Bug Fixes - Fix a bug where cycles in dependent modules could enter infinite recursion ([#65291](https://github.com/WordPress/gutenberg/pull/65291)). diff --git a/packages/dependency-extraction-webpack-plugin/lib/index.js b/packages/dependency-extraction-webpack-plugin/lib/index.js index 529fb339d15a1..cf780d7370dcf 100644 --- a/packages/dependency-extraction-webpack-plugin/lib/index.js +++ b/packages/dependency-extraction-webpack-plugin/lib/index.js @@ -162,6 +162,14 @@ class DependencyExtractionWebpackPlugin { compiler.hooks.thisCompilation.tap( this.constructor.name, ( compilation ) => { + compilation.hooks.processAssets.tap( + { + name: this.constructor.name, + stage: compiler.webpack.Compilation + .PROCESS_ASSETS_STAGE_OPTIMIZE_COMPATIBILITY, + }, + () => this.checkForMagicComments( compilation ) + ); compilation.hooks.processAssets.tap( { name: this.constructor.name, @@ -174,6 +182,60 @@ class DependencyExtractionWebpackPlugin { ); } + /** + * Check for magic comments before minification, so minification doesn't have to preserve them. + * @param {webpack.Compilation} compilation + */ + checkForMagicComments( compilation ) { + // Accumulate all entrypoint chunks, some of them shared + const entrypointChunks = new Set(); + for ( const entrypoint of compilation.entrypoints.values() ) { + for ( const chunk of entrypoint.chunks ) { + entrypointChunks.add( chunk ); + } + } + + // Process each entrypoint chunk independently + for ( const chunk of entrypointChunks ) { + const chunkFiles = Array.from( chunk.files ); + + const jsExtensionRegExp = this.useModules ? /\.m?js$/i : /\.js$/i; + + const chunkJSFile = chunkFiles.find( ( f ) => + jsExtensionRegExp.test( f ) + ); + if ( ! chunkJSFile ) { + // There's no JS file in this chunk, no work for us. Typically a `style.css` from cache group. + continue; + } + + // Prepare to look for magic comments, in order to decide whether + // `wp-polyfill` is needed. + const processContentsForMagicComments = ( content ) => { + const magicComments = []; + + if ( content.includes( '/* wp:polyfill */' ) ) { + magicComments.push( 'wp-polyfill' ); + } + + return magicComments; + }; + + // Go through the assets to process the sources. + // This allows us to look for magic comments. + chunkFiles.sort().forEach( ( filename ) => { + const asset = compilation.getAsset( filename ); + const content = asset.source.buffer(); + + const wpMagicComments = + processContentsForMagicComments( content ); + compilation.updateAsset( filename, ( v ) => v, { + wpMagicComments, + } ); + } ); + } + } + /** @param {webpack.Compilation} compilation */ addAssets( compilation ) { const { @@ -286,8 +348,11 @@ class DependencyExtractionWebpackPlugin { // Prepare to look for magic comments, in order to decide whether // `wp-polyfill` is needed. - const processContentsForMagicComments = ( content ) => { - if ( content.includes( '/* wp:polyfill */' ) ) { + const handleMagicComments = ( info ) => { + if ( ! info ) { + return; + } + if ( info.includes( 'wp-polyfill' ) ) { chunkStaticDeps.add( 'wp-polyfill' ); } }; @@ -299,7 +364,7 @@ class DependencyExtractionWebpackPlugin { const content = asset.source.buffer(); processContentsForHash( content ); - processContentsForMagicComments( content ); + handleMagicComments( asset.info.wpMagicComments ); } ); // Finalise hash. diff --git a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap index 903c9658250b1..f0d418851103b 100644 --- a/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap +++ b/packages/dependency-extraction-webpack-plugin/test/__snapshots__/build.js.snap @@ -257,6 +257,13 @@ exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comm exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comment\` should produce expected output: External modules should match snapshot 1`] = `[]`; +exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comment-minified\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` +" array('wp-polyfill'), 'version' => '31d6cfe0d16ae931b73c', 'type' => 'module'); +" +`; + +exports[`DependencyExtractionWebpackPlugin modules Webpack \`polyfill-magic-comment-minified\` should produce expected output: External modules should match snapshot 1`] = `[]`; + exports[`DependencyExtractionWebpackPlugin modules Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'a.asset.php' should match snapshot 1`] = ` " array('@wordpress/blob'), 'version' => 'a1906cfc819b623c86f8', 'type' => 'module'); " @@ -666,6 +673,13 @@ exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comm exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comment\` should produce expected output: External modules should match snapshot 1`] = `[]`; +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comment-minified\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = ` +" array('wp-polyfill'), 'version' => '31d6cfe0d16ae931b73c'); +" +`; + +exports[`DependencyExtractionWebpackPlugin scripts Webpack \`polyfill-magic-comment-minified\` should produce expected output: External modules should match snapshot 1`] = `[]`; + exports[`DependencyExtractionWebpackPlugin scripts Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'a.asset.php' should match snapshot 1`] = ` " array('wp-blob'), 'version' => 'd3cda564b538b44d38ef'); " diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment-minified/index.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment-minified/index.js new file mode 100644 index 0000000000000..d98678f44cb69 --- /dev/null +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment-minified/index.js @@ -0,0 +1,3 @@ +/* wp:polyfill */ + +// Nothing else, really. diff --git a/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment-minified/webpack.config.js b/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment-minified/webpack.config.js new file mode 100644 index 0000000000000..be01328d675d0 --- /dev/null +++ b/packages/dependency-extraction-webpack-plugin/test/fixtures/polyfill-magic-comment-minified/webpack.config.js @@ -0,0 +1,11 @@ +/** + * Internal dependencies + */ +const DependencyExtractionWebpackPlugin = require( '../../..' ); + +module.exports = { + optimization: { + minimize: true, + }, + plugins: [ new DependencyExtractionWebpackPlugin() ], +}; diff --git a/tools/webpack/shared.js b/tools/webpack/shared.js index c8c5b05c7d151..f30d3a830f3eb 100644 --- a/tools/webpack/shared.js +++ b/tools/webpack/shared.js @@ -25,7 +25,7 @@ const baseConfig = { parallel: true, terserOptions: { output: { - comments: /(translators:|wp:polyfill)/i, + comments: /translators:/i, }, compress: { passes: 2,