Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependencies webpack plugin: Add new option to combine assets files into one file #20330

Merged
merged 3 commits into from
Feb 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/dependency-extraction-webpack-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## Master

### New Features

- The plugin now supports optional `combineAssets` options. When this flag is set to `true`, all information about assets is combined into a single `assets.(json|php)` file generated in the output directory ([#20330](https://github.com/WordPress/gutenberg/pull/20330)).

## 2.0.0 (2019-09-16)

### Breaking Changes
Expand Down
9 changes: 8 additions & 1 deletion packages/dependency-extraction-webpack-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,13 @@ module.exports = {

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

##### `combineAssets`

- Type: boolean
- Default: `false`

By default, one asset file is created for each entry point. When this flag is set to `true`, all information about assets is combined into a single `assets.(json|php)` file generated in the output directory.

##### `useDefaults`

- Type: boolean
Expand Down Expand Up @@ -217,7 +224,7 @@ Enqueue your script as usual and read the script dependencies dynamically:
$script_path = 'path/to/script.js';
$script_asset_path = 'path/to/script.asset.php';
$script_asset = file_exists( $script_asset_path )
? require( $script_asset_path )
? require( $script_asset_path )
: array( 'dependencies' => array(), 'version' => filemtime( $script_path ) );
$script_url = plugins_url( $script_path, __FILE__ );
wp_enqueue_script( 'script', $script_url, $script_asset['dependencies'], $script_asset['version'] );
Expand Down
67 changes: 49 additions & 18 deletions packages/dependency-extraction-webpack-plugin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
const { createHash } = require( 'crypto' );
const json2php = require( 'json2php' );
const path = require( 'path' );
const { ExternalsPlugin } = require( 'webpack' );
const { RawSource } = require( 'webpack-sources' );

Expand All @@ -18,6 +19,7 @@ class DependencyExtractionWebpackPlugin {
constructor( options ) {
this.options = Object.assign(
{
combineAssets: false,
injectPolyfill: false,
outputFormat: 'php',
useDefaults: true,
Expand Down Expand Up @@ -102,7 +104,12 @@ class DependencyExtractionWebpackPlugin {
const { filename: outputFilename } = output;

compiler.hooks.emit.tap( this.constructor.name, ( compilation ) => {
const { injectPolyfill, outputFormat } = this.options;
const {
combineAssets,
injectPolyfill,
outputFormat,
} = this.options;
const combinedAssetsData = {};

// Process each entry point independently.
for ( const [
Expand Down Expand Up @@ -130,37 +137,61 @@ class DependencyExtractionWebpackPlugin {

const runtimeChunk = entrypoint.getRuntimeChunk();

// Get a stable, stringified representation of the WordPress script asset.
const assetString = this.stringify( {
const assetData = {
// Get a sorted array so we can produce a stable, stringified representation.
dependencies: Array.from(
gziolo marked this conversation as resolved.
Show resolved Hide resolved
entrypointExternalizedWpDeps
).sort(),
version: runtimeChunk.hash,
} );
};

const assetString = this.stringify( assetData );

// Determine a filename for the asset file.
const [ filename, query ] = entrypointName.split( '?', 2 );
const assetFilename = compilation
.getPath( outputFilename, {
chunk: runtimeChunk,
filename,
query,
basename: basename( filename ),
contentHash: createHash( 'md4' )
.update( assetString )
.digest( 'hex' ),
} )
.replace(
/\.js$/i,
'.asset.' + ( outputFormat === 'php' ? 'php' : 'json' )
);
const buildFilename = compilation.getPath( outputFilename, {
chunk: runtimeChunk,
filename,
query,
basename: basename( filename ),
contentHash: createHash( 'md4' )
.update( assetString )
.digest( 'hex' ),
} );

if ( combineAssets ) {
combinedAssetsData[ buildFilename ] = assetData;
sirreal marked this conversation as resolved.
Show resolved Hide resolved
continue;
}

const 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.push( assetFilename );
}

if ( combineAssets ) {
const outputFolder = compiler.options.output.path;
const assetsFilePath = path.resolve(
outputFolder,
'assets.' + ( outputFormat === 'php' ? 'php' : 'json' )
);
const assetsFilename = path.relative(
outputFolder,
assetsFilePath
);

// Add source into compilation for webpack to output.
compilation.assets[ assetsFilename ] = new RawSource(
this.stringify( combinedAssetsData )
);
}
} );
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,39 @@
// 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' => '2ac177723ec97b400d9b7c46f5270974'), 'fileB.js' => array('dependencies' => array('wp-token-list'), 'version' => 'bddb08fb8608759738528b9de111454d'));"`;

exports[`Webpack \`combine-assets\` should produce expected output: External modules should match snapshot 1`] = `
Array [
Object {
"externalType": "this",
"request": Object {
"this": Array [
"wp",
"blob",
],
},
"userRequest": "@wordpress/blob",
},
Object {
"externalType": "this",
"request": Object {
"this": Array [
"wp",
"tokenList",
],
},
"userRequest": "@wordpress/token-list",
},
Object {
"externalType": "this",
"request": Object {
"this": "lodash",
},
"userRequest": "lodash",
},
]
`;

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

exports[`Webpack \`dynamic-import\` should produce expected output: External modules should match snapshot 1`] = `
Expand Down
8 changes: 6 additions & 2 deletions packages/dependency-extraction-webpack-plugin/test/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,16 @@ describe.each( configFixtures )( 'Webpack `%s`', ( configCase ) => {
expect( err ).toBeNull();

const assetFiles = glob(
`${ outputDirectory }/*.asset.@(json|php)`
`${ outputDirectory }/+(*.asset|assets).@(json|php)`
);
const expectedLength =
const hasCombinedAssets = ( options.plugins || [] ).some(
( plugin ) => !! ( plugin.options || {} ).combineAssets
);
const entrypointCount =
typeof options.entry === 'object'
? Object.keys( options.entry ).length
: 1;
const expectedLength = hasCombinedAssets ? 1 : entrypointCount;
expect( assetFiles ).toHaveLength( expectedLength );

// Asset files should match.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* External dependencies
*/
import { isEmpty } from 'lodash';

/**
* WordPress dependencies
*/
import { isBlobURL } from '@wordpress/blob';

isEmpty( isBlobURL( '' ) );
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* WordPress dependencies
*/
import TokenList from '@wordpress/token-list';

const tokens = new TokenList( 'abc def' );
tokens.add( 'ghi' );
tokens.remove( 'def' );
tokens.replace( 'abc', 'xyz' );
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const DependencyExtractionWebpackPlugin = require( '../../..' );

module.exports = {
entry: {
fileA: './file-a.js',
fileB: './file-b.js',
},
plugins: [
new DependencyExtractionWebpackPlugin( {
combineAssets: true,
} ),
],
};