Skip to content

Commit

Permalink
Dependency Extraction Webpack Plugin: Make the plugin work when using…
Browse files Browse the repository at this point in the history
… `optimizations.runtimeChunk = 'single'` (#26214)

* Include asset filenames in snapshots

* Use entrypoint chunk instead of runtime chunk

This results in the asset files being named after the entry points,
instead of the runtime chunk when using `runtimeChunk = 'single'`.

Fixes #24352

* Add outputFilename option

Allows specifying the asset filename format separately from the output
filename format. This is useful when the output filenames include a
hash.
  • Loading branch information
stefanfisk authored Nov 24, 2021
1 parent 50b19e7 commit d2d673d
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 19 deletions.
7 changes: 7 additions & 0 deletions packages/dependency-extraction-webpack-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ module.exports = {

The output format for the generated asset file. There are two options available: 'php' or 'json'.

##### `outputFilename`

- Type: string | function
- Default: null

The filename for the generated asset file. Accepts the same values as the Webpack `output.filename` option.

##### `combineAssets`

- Type: boolean
Expand Down
36 changes: 28 additions & 8 deletions packages/dependency-extraction-webpack-plugin/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class DependencyExtractionWebpackPlugin {
externalizedReport: false,
injectPolyfill: false,
outputFormat: 'php',
outputFilename: null,
useDefaults: true,
},
options
Expand Down Expand Up @@ -143,6 +144,7 @@ class DependencyExtractionWebpackPlugin {
externalizedReport,
injectPolyfill,
outputFormat,
outputFilename,
} = this.options;

// Dump actually externalized dependencies to a report file.
Expand Down Expand Up @@ -196,12 +198,14 @@ class DependencyExtractionWebpackPlugin {
}
}

const runtimeChunk = entrypoint.getRuntimeChunk();
const entrypointChunk = isWebpack4
? entrypoint.chunks.find( ( c ) => c.name === entrypointName )
: entrypoint.getEntrypointChunk();

const assetData = {
// Get a sorted array so we can produce a stable, stringified representation.
dependencies: Array.from( entrypointExternalizedWpDeps ).sort(),
version: runtimeChunk.hash,
version: entrypointChunk.hash,
};

const assetString = this.stringify( assetData );
Expand All @@ -211,7 +215,7 @@ class DependencyExtractionWebpackPlugin {
const buildFilename = compilation.getPath(
compiler.options.output.filename,
{
chunk: runtimeChunk,
chunk: entrypointChunk,
filename,
query,
basename: basename( filename ),
Expand All @@ -226,14 +230,30 @@ class DependencyExtractionWebpackPlugin {
continue;
}

const assetFilename = buildFilename.replace(
/\.js$/i,
'.asset.' + ( outputFormat === 'php' ? 'php' : 'json' )
);
let assetFilename;

if ( outputFilename ) {
assetFilename = compilation.getPath( outputFilename, {
chunk: entrypointChunk,
filename,
query,
basename: basename( filename ),
contentHash: createHash( 'md4' )
.update( assetString )
.digest( 'hex' ),
} );
} else {
assetFilename = buildFilename.replace(
/\.js$/i,
'.asset.' + ( outputFormat === 'php' ? 'php' : 'json' )
);
}

// Add source and file into compilation for webpack to output.
compilation.assets[ assetFilename ] = new RawSource( assetString );
runtimeChunk.files[ isWebpack4 ? 'push' : 'add' ]( assetFilename );
entrypointChunk.files[ isWebpack4 ? 'push' : 'add' ](
assetFilename
);
}

if ( combineAssets ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ declare interface DependencyExtractionWebpackPluginOptions {
injectPolyfill?: boolean;
useDefaults?: boolean;
outputFormat?: 'php' | 'json';
outputFilename?: string | Function,
requestToExternal?: ( request: string ) => string | string[] | undefined;
requestToHandle?: ( request: string ) => string | undefined;
combinedOutputFile?: string | null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Webpack \`combine-assets\` should produce expected output: Asset file should match snapshot 1`] = `"<?php return array('fileA.js' => array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'bedcdcf40ea252047201aa0ee74a9377'), 'fileB.js' => array('dependencies' => array('wp-token-list'), 'version' => 'bec6f52af59733fff68cf46dbce8e226'));"`;
exports[`Webpack \`combine-assets\` should produce expected output: Asset file 'assets.php' should match snapshot 1`] = `"<?php return array('fileA.js' => array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'bedcdcf40ea252047201aa0ee74a9377'), 'fileB.js' => array('dependencies' => array('wp-token-list'), 'version' => 'bec6f52af59733fff68cf46dbce8e226'));"`;

exports[`Webpack \`combine-assets\` should produce expected output: External modules should match snapshot 1`] = `
Array [
Expand Down Expand Up @@ -28,7 +28,7 @@ Array [
]
`;

exports[`Webpack \`dynamic-import\` should produce expected output: Asset file should match snapshot 1`] = `"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'd56d3ad4bd3fcf9605c3d640d369cde4');"`;
exports[`Webpack \`dynamic-import\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = `"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'd56d3ad4bd3fcf9605c3d640d369cde4');"`;

exports[`Webpack \`dynamic-import\` should produce expected output: External modules should match snapshot 1`] = `
Array [
Expand All @@ -48,7 +48,7 @@ Array [
]
`;

exports[`Webpack \`function-output-filename\` should produce expected output: Asset file should match snapshot 1`] = `"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '844c4b1f2a6db3a13416e9ea339e6334');"`;
exports[`Webpack \`function-output-filename\` should produce expected output: Asset file 'chunk--main--main.asset.php' should match snapshot 1`] = `"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '844c4b1f2a6db3a13416e9ea339e6334');"`;

exports[`Webpack \`function-output-filename\` should produce expected output: External modules should match snapshot 1`] = `
Array [
Expand All @@ -68,7 +68,7 @@ Array [
]
`;

exports[`Webpack \`has-extension-suffix\` should produce expected output: Asset file should match snapshot 1`] = `"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'c35663ec29b695840a3c52d6fcc041c3');"`;
exports[`Webpack \`has-extension-suffix\` should produce expected output: Asset file 'index.min.asset.php' should match snapshot 1`] = `"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => 'c35663ec29b695840a3c52d6fcc041c3');"`;

exports[`Webpack \`has-extension-suffix\` should produce expected output: External modules should match snapshot 1`] = `
Array [
Expand All @@ -88,15 +88,55 @@ Array [
]
`;

exports[`Webpack \`no-default\` should produce expected output: Asset file should match snapshot 1`] = `"<?php return array('dependencies' => array(), 'version' => 'feb97b1f3aec28878f5872b60f37567b');"`;
exports[`Webpack \`no-default\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = `"<?php return array('dependencies' => array(), 'version' => 'feb97b1f3aec28878f5872b60f37567b');"`;

exports[`Webpack \`no-default\` should produce expected output: External modules should match snapshot 1`] = `Array []`;

exports[`Webpack \`no-deps\` should produce expected output: Asset file should match snapshot 1`] = `"<?php return array('dependencies' => array(), 'version' => 'd77fa1fabdfc18f9520a9325e0768b24');"`;
exports[`Webpack \`no-deps\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = `"<?php return array('dependencies' => array(), 'version' => 'd77fa1fabdfc18f9520a9325e0768b24');"`;

exports[`Webpack \`no-deps\` should produce expected output: External modules should match snapshot 1`] = `Array []`;

exports[`Webpack \`output-format-json\` should produce expected output: Asset file should match snapshot 1`] = `"{\\"dependencies\\":[\\"lodash\\"],\\"version\\":\\"c0593f49cf023b00b43d085327cd4e3b\\"}"`;
exports[`Webpack \`option-function-output-filename\` should produce expected output: Asset file 'chunk--main--main.asset.php' should match snapshot 1`] = `"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '844c4b1f2a6db3a13416e9ea339e6334');"`;

exports[`Webpack \`option-function-output-filename\` should produce expected output: External modules should match snapshot 1`] = `
Array [
Object {
"externalType": "window",
"request": "lodash",
"userRequest": "lodash",
},
Object {
"externalType": "window",
"request": Array [
"wp",
"blob",
],
"userRequest": "@wordpress/blob",
},
]
`;

exports[`Webpack \`option-output-filename\` should produce expected output: Asset file 'main-foo.asset.php' should match snapshot 1`] = `"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '844c4b1f2a6db3a13416e9ea339e6334');"`;

exports[`Webpack \`option-output-filename\` should produce expected output: External modules should match snapshot 1`] = `
Array [
Object {
"externalType": "window",
"request": "lodash",
"userRequest": "lodash",
},
Object {
"externalType": "window",
"request": Array [
"wp",
"blob",
],
"userRequest": "@wordpress/blob",
},
]
`;

exports[`Webpack \`output-format-json\` should produce expected output: Asset file 'main.asset.json' should match snapshot 1`] = `"{\\"dependencies\\":[\\"lodash\\"],\\"version\\":\\"c0593f49cf023b00b43d085327cd4e3b\\"}"`;

exports[`Webpack \`output-format-json\` should produce expected output: External modules should match snapshot 1`] = `
Array [
Expand All @@ -108,7 +148,7 @@ Array [
]
`;

exports[`Webpack \`overrides\` should produce expected output: Asset file should match snapshot 1`] = `"<?php return array('dependencies' => array('wp-blob', 'wp-script-handle-for-rxjs', 'wp-url'), 'version' => '90aabe80a22b120d4ce792caba9e2238');"`;
exports[`Webpack \`overrides\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = `"<?php return array('dependencies' => array('wp-blob', 'wp-script-handle-for-rxjs', 'wp-url'), 'version' => '90aabe80a22b120d4ce792caba9e2238');"`;

exports[`Webpack \`overrides\` should produce expected output: External modules should match snapshot 1`] = `
Array [
Expand Down Expand Up @@ -144,7 +184,29 @@ Array [
]
`;

exports[`Webpack \`wordpress\` should produce expected output: Asset file should match snapshot 1`] = `"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '844c4b1f2a6db3a13416e9ea339e6334');"`;
exports[`Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'a.asset.php' should match snapshot 1`] = `"<?php return array('dependencies' => array('wp-blob'), 'version' => '8f74c54ba0be0fd357a8594c9eda1f35');"`;

exports[`Webpack \`runtime-chunk-single\` should produce expected output: Asset file 'b.asset.php' should match snapshot 1`] = `"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '4ad01639f1af1b6624a0d18cbb94e4e6');"`;

exports[`Webpack \`runtime-chunk-single\` should produce expected output: External modules should match snapshot 1`] = `
Array [
Object {
"externalType": "window",
"request": "lodash",
"userRequest": "lodash",
},
Object {
"externalType": "window",
"request": Array [
"wp",
"blob",
],
"userRequest": "@wordpress/blob",
},
]
`;

exports[`Webpack \`wordpress\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = `"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '844c4b1f2a6db3a13416e9ea339e6334');"`;

exports[`Webpack \`wordpress\` should produce expected output: External modules should match snapshot 1`] = `
Array [
Expand All @@ -164,7 +226,7 @@ Array [
]
`;

exports[`Webpack \`wordpress-require\` should produce expected output: Asset file should match snapshot 1`] = `"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '2a613fdd9e36fb13cd706b2d42a66ba3');"`;
exports[`Webpack \`wordpress-require\` should produce expected output: Asset file 'main.asset.php' should match snapshot 1`] = `"<?php return array('dependencies' => array('lodash', 'wp-blob'), 'version' => '2a613fdd9e36fb13cd706b2d42a66ba3');"`;

exports[`Webpack \`wordpress-require\` should produce expected output: External modules should match snapshot 1`] = `
Array [
Expand Down
6 changes: 5 additions & 1 deletion packages/dependency-extraction-webpack-plugin/test/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,13 @@ describe.each( configFixtures )( 'Webpack `%s`', ( configCase ) => {

// Asset files should match.
assetFiles.forEach( ( assetFile ) => {
const assetBasename = path.basename( assetFile );

expect(
fs.readFileSync( assetFile, 'utf-8' )
).toMatchSnapshot( 'Asset file should match snapshot' );
).toMatchSnapshot(
`Asset file '${ assetBasename }' should match snapshot`
);
} );

const compareByModuleIdentifier = ( m1, m2 ) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* WordPress dependencies
*/
import { isBlobURL } from '@wordpress/blob';

/**
* External dependencies
*/
import _ from 'lodash';

_.isEmpty( isBlobURL( '' ) );
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Internal dependencies
*/
const DependencyExtractionWebpackPlugin = require( '../../..' );

module.exports = {
plugins: [
new DependencyExtractionWebpackPlugin( {
outputFilename( chunkData ) {
return `chunk--${ chunkData.chunk.name }--[name].asset.php`;
},
} ),
],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* WordPress dependencies
*/
import { isBlobURL } from '@wordpress/blob';

/**
* External dependencies
*/
import _ from 'lodash';

_.isEmpty( isBlobURL( '' ) );
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Internal dependencies
*/
const DependencyExtractionWebpackPlugin = require( '../../..' );

module.exports = {
plugins: [
new DependencyExtractionWebpackPlugin( {
outputFilename: '[name]-foo.asset.php',
} ),
],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* WordPress dependencies
*/
import { isBlobURL } from '@wordpress/blob';

/**
* External dependencies
*/
import atob from 'atob';

isBlobURL( '' );
atob( 'SGVsbG8sIFdvcmxkIQ==' );
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* WordPress dependencies
*/
import { isBlobURL } from '@wordpress/blob';

/**
* External dependencies
*/
import _ from 'lodash';

_.isEmpty( isBlobURL( '' ) );
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Internal dependencies
*/
const DependencyExtractionWebpackPlugin = require( '../../..' );

module.exports = {
entry: {
a: './a',
b: './b',
},
plugins: [ new DependencyExtractionWebpackPlugin() ],
optimization: {
runtimeChunk: 'single',
},
};

0 comments on commit d2d673d

Please sign in to comment.