@wordpress/dependency-extraction-webpack-plugin 3.4.2 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 3.7.0 (2022-07-13)
6
+
7
+ ### New Features
8
+
9
+ - Output asset files for shared chunks, too ([#41002](https://github.com/WordPress/gutenberg/pull/41002)).
10
+
11
+ ## 3.5.0 (2022-05-18)
12
+
13
+ ### Bug Fix
14
+
15
+ - Use OpenSSL provider supported in Node 17+ when calling `crypto.createHash` ([#40503](https://github.com/WordPress/gutenberg/pull/40503)).
16
+ - Add new line at the end of generated `*.asset.php` files ([#40753](https://github.com/WordPress/gutenberg/pull/40753)).
17
+ - Calculate version hashes based on output file contents rather than input files and other Webpack internal state ([#34969](https://github.com/WordPress/gutenberg/pull/34969)).
18
+
5
19
  ## 3.3.0 (2022-01-27)
6
20
 
7
21
  - Add the optional `externalizedReportFile` option ([#35106](https://github.com/WordPress/gutenberg/pull/35106)).
package/lib/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- const { createHash } = require( 'crypto' );
5
4
  const path = require( 'path' );
6
5
  const webpack = require( 'webpack' );
7
6
  // In webpack 5 there is a `webpack.sources` field but for webpack 4 we have to fallback to the `webpack-sources` package.
8
7
  const { RawSource } = webpack.sources || require( 'webpack-sources' );
9
8
  const json2php = require( 'json2php' );
10
9
  const isWebpack4 = webpack.version.startsWith( '4.' );
10
+ const { createHash } = webpack.util;
11
11
 
12
12
  /**
13
13
  * Internal dependencies
@@ -106,7 +106,7 @@ class DependencyExtractionWebpackPlugin {
106
106
  if ( this.options.outputFormat === 'php' ) {
107
107
  return `<?php return ${ json2php(
108
108
  JSON.parse( JSON.stringify( asset ) )
109
- ) };`;
109
+ ) };\n`;
110
110
  }
111
111
 
112
112
  return JSON.stringify( asset );
@@ -117,7 +117,7 @@ class DependencyExtractionWebpackPlugin {
117
117
 
118
118
  if ( isWebpack4 ) {
119
119
  compiler.hooks.emit.tap( this.constructor.name, ( compilation ) =>
120
- this.addAssets( compilation, compiler )
120
+ this.addAssets( compilation )
121
121
  );
122
122
  } else {
123
123
  compiler.hooks.thisCompilation.tap(
@@ -126,18 +126,17 @@ class DependencyExtractionWebpackPlugin {
126
126
  compilation.hooks.processAssets.tap(
127
127
  {
128
128
  name: this.constructor.name,
129
- stage:
130
- compiler.webpack.Compilation
131
- .PROCESS_ASSETS_STAGE_ADDITIONAL,
129
+ stage: compiler.webpack.Compilation
130
+ .PROCESS_ASSETS_STAGE_ANALYSE,
132
131
  },
133
- () => this.addAssets( compilation, compiler )
132
+ () => this.addAssets( compilation )
134
133
  );
135
134
  }
136
135
  );
137
136
  }
138
137
  }
139
138
 
140
- addAssets( compilation, compiler ) {
139
+ addAssets( compilation ) {
141
140
  const {
142
141
  combineAssets,
143
142
  combinedOutputFile,
@@ -163,106 +162,102 @@ class DependencyExtractionWebpackPlugin {
163
162
 
164
163
  const combinedAssetsData = {};
165
164
 
166
- // Process each entry point independently.
167
- for ( const [
168
- entrypointName,
169
- entrypoint,
170
- ] of compilation.entrypoints.entries() ) {
171
- const entrypointExternalizedWpDeps = new Set();
165
+ // Accumulate all entrypoint chunks, some of them shared
166
+ const entrypointChunks = new Set();
167
+ for ( const entrypoint of compilation.entrypoints.values() ) {
168
+ for ( const chunk of entrypoint.chunks ) {
169
+ entrypointChunks.add( chunk );
170
+ }
171
+ }
172
+
173
+ // Process each entrypoint chunk independently
174
+ for ( const chunk of entrypointChunks ) {
175
+ const chunkFiles = Array.from( chunk.files );
176
+
177
+ const chunkJSFile = chunkFiles.find( ( f ) => /\.js$/i.test( f ) );
178
+ if ( ! chunkJSFile ) {
179
+ // There's no JS file in this chunk, no work for us. Typically a `style.css` from cache group.
180
+ continue;
181
+ }
182
+
183
+ const chunkDeps = new Set();
172
184
  if ( injectPolyfill ) {
173
- entrypointExternalizedWpDeps.add( 'wp-polyfill' );
185
+ chunkDeps.add( 'wp-polyfill' );
174
186
  }
175
187
 
176
188
  const processModule = ( { userRequest } ) => {
177
189
  if ( this.externalizedDeps.has( userRequest ) ) {
178
- const scriptDependency = this.mapRequestToDependency(
179
- userRequest
180
- );
181
- entrypointExternalizedWpDeps.add( scriptDependency );
190
+ chunkDeps.add( this.mapRequestToDependency( userRequest ) );
182
191
  }
183
192
  };
184
193
 
185
194
  // Search for externalized modules in all chunks.
186
- for ( const chunk of entrypoint.chunks ) {
187
- const modulesIterable = isWebpack4
188
- ? chunk.modulesIterable
189
- : compilation.chunkGraph.getChunkModules( chunk );
190
- for ( const chunkModule of modulesIterable ) {
191
- processModule( chunkModule );
192
- // Loop through submodules of ConcatenatedModule.
193
- if ( chunkModule.modules ) {
194
- for ( const concatModule of chunkModule.modules ) {
195
- processModule( concatModule );
196
- }
195
+ const modulesIterable = isWebpack4
196
+ ? chunk.modulesIterable
197
+ : compilation.chunkGraph.getChunkModules( chunk );
198
+ for ( const chunkModule of modulesIterable ) {
199
+ processModule( chunkModule );
200
+ // Loop through submodules of ConcatenatedModule.
201
+ if ( chunkModule.modules ) {
202
+ for ( const concatModule of chunkModule.modules ) {
203
+ processModule( concatModule );
197
204
  }
198
205
  }
199
206
  }
200
207
 
201
- const entrypointChunk = isWebpack4
202
- ? entrypoint.chunks.find( ( c ) => c.name === entrypointName )
203
- : entrypoint.getEntrypointChunk();
208
+ // Go through the assets and hash the sources. We can't just use
209
+ // `chunk.contentHash` because that's not updated when
210
+ // assets are minified. In practice the hash is updated by
211
+ // `RealContentHashPlugin` after minification, but it only modifies
212
+ // already-produced asset filenames and the updated hash is not
213
+ // available to plugins.
214
+ const { hashFunction, hashDigest, hashDigestLength } =
215
+ compilation.outputOptions;
216
+
217
+ const contentHash = chunkFiles
218
+ .sort()
219
+ .reduce( ( hash, filename ) => {
220
+ const asset = compilation.getAsset( filename );
221
+ return hash.update( asset.source.buffer() );
222
+ }, createHash( hashFunction ) )
223
+ .digest( hashDigest )
224
+ .slice( 0, hashDigestLength );
204
225
 
205
226
  const assetData = {
206
227
  // Get a sorted array so we can produce a stable, stringified representation.
207
- dependencies: Array.from( entrypointExternalizedWpDeps ).sort(),
208
- version: entrypointChunk.hash,
228
+ dependencies: Array.from( chunkDeps ).sort(),
229
+ version: contentHash,
209
230
  };
210
231
 
211
- const assetString = this.stringify( assetData );
212
-
213
- // Determine a filename for the asset file.
214
- const [ filename, query ] = entrypointName.split( '?', 2 );
215
- const buildFilename = compilation.getPath(
216
- compiler.options.output.filename,
217
- {
218
- chunk: entrypointChunk,
219
- filename,
220
- query,
221
- basename: basename( filename ),
222
- contentHash: createHash( 'md4' )
223
- .update( assetString )
224
- .digest( 'hex' ),
225
- }
226
- );
227
-
228
232
  if ( combineAssets ) {
229
- combinedAssetsData[ buildFilename ] = assetData;
233
+ combinedAssetsData[ chunkJSFile ] = assetData;
230
234
  continue;
231
235
  }
232
236
 
233
237
  let assetFilename;
234
-
235
238
  if ( outputFilename ) {
236
239
  assetFilename = compilation.getPath( outputFilename, {
237
- chunk: entrypointChunk,
238
- filename,
239
- query,
240
- basename: basename( filename ),
241
- contentHash: createHash( 'md4' )
242
- .update( assetString )
243
- .digest( 'hex' ),
240
+ chunk,
241
+ filename: chunkJSFile,
242
+ contentHash,
244
243
  } );
245
244
  } else {
246
- assetFilename = buildFilename.replace(
247
- /\.js$/i,
248
- '.asset.' + ( outputFormat === 'php' ? 'php' : 'json' )
249
- );
245
+ const suffix =
246
+ '.asset.' + ( outputFormat === 'php' ? 'php' : 'json' );
247
+ assetFilename = compilation
248
+ .getPath( '[file]', { filename: chunkJSFile } )
249
+ .replace( /\.js$/i, suffix );
250
250
  }
251
251
 
252
252
  // Add source and file into compilation for webpack to output.
253
- compilation.assets[ assetFilename ] = new RawSource( assetString );
254
- entrypointChunk.files[ isWebpack4 ? 'push' : 'add' ](
255
- assetFilename
253
+ compilation.assets[ assetFilename ] = new RawSource(
254
+ this.stringify( assetData )
256
255
  );
256
+ chunk.files[ isWebpack4 ? 'push' : 'add' ]( assetFilename );
257
257
  }
258
258
 
259
259
  if ( combineAssets ) {
260
- // Assert the `string` type for output path.
261
- // The type indicates the option may be `undefined`.
262
- // However, at this point in compilation, webpack has filled the options in if
263
- // they were not provided.
264
- const outputFolder = /** @type {{path:string}} */ ( compiler.options
265
- .output ).path;
260
+ const outputFolder = compilation.outputOptions.path;
266
261
 
267
262
  const assetsFilePath = path.resolve(
268
263
  outputFolder,
@@ -282,11 +277,4 @@ class DependencyExtractionWebpackPlugin {
282
277
  }
283
278
  }
284
279
 
285
- function basename( name ) {
286
- if ( ! name.includes( '/' ) ) {
287
- return name;
288
- }
289
- return name.substr( name.lastIndexOf( '/' ) + 1 );
290
- }
291
-
292
280
  module.exports = DependencyExtractionWebpackPlugin;
package/lib/types.d.ts CHANGED
@@ -11,7 +11,7 @@ declare interface DependencyExtractionWebpackPluginOptions {
11
11
  injectPolyfill?: boolean;
12
12
  useDefaults?: boolean;
13
13
  outputFormat?: 'php' | 'json';
14
- outputFilename?: string | Function,
14
+ outputFilename?: string | Function;
15
15
  requestToExternal?: ( request: string ) => string | string[] | undefined;
16
16
  requestToHandle?: ( request: string ) => string | undefined;
17
17
  combinedOutputFile?: string | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/dependency-extraction-webpack-plugin",
3
- "version": "3.4.2",
3
+ "version": "3.7.0",
4
4
  "description": "Extract WordPress script dependencies from webpack bundles.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -38,5 +38,5 @@
38
38
  "publishConfig": {
39
39
  "access": "public"
40
40
  },
41
- "gitHead": "446565ecaa40370173c18926535e975ec5652b71"
41
+ "gitHead": "9d9d33bbdf317a4381b8ca1713e43bb50df653b3"
42
42
  }