-
Notifications
You must be signed in to change notification settings - Fork 10.7k
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
Improve webpack cache-busting version parameter by using file contents hash #44838
Merged
Merged
Changes from 13 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
ec0ba74
Update webpack config to use file content hash for chunks and generat…
chihsuan d04bb16
Use StyleAssetPlugin to generate style.asset.php
chihsuan 4d66518
Remove unneed ?ver=<version> code
chihsuan 2f63753
Use file hash from asset file when SCRIPT_DEBUG is off
chihsuan 76fc585
Load payment method promotions in admin_enqueue_scripts
chihsuan 7c4d57d
Add changefile(s) from automation for the following project(s): @wooc…
invalid-email-address cad2b69
Add json2php
chihsuan 7a2e18d
Update doc
chihsuan 24b150c
Update pnpm-lock.yaml
chihsuan e68e6d7
Fix add_print_shipping_label_script
chihsuan 4b927f8
Add a comment to style-asset-plugin.js
chihsuan 8d29407
Change register_style to use WC_ADMIN_DIST_CSS_FOLDER
chihsuan 5591fcb
Reset the outputNormal object to avoid duplicate files
chihsuan 595e99f
Fix type error
chihsuan File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
/** | ||
* Add an asset file for each entry point that contains the current version calculated for the current source code. | ||
* | ||
* This is modified from WP dependency-extraction-webpack-plugin plugin: | ||
* https://github.com/WordPress/gutenberg/tree/a04a8e94e8b93ba60441c6534e21f4c3c26ff1bc/packages/dependency-extraction-webpack-plugin | ||
* | ||
* We can contribute this back to the original plugin in the future and remove this file. | ||
*/ | ||
|
||
/** | ||
* External dependencies | ||
*/ | ||
const path = require( 'path' ); | ||
const webpack = require( 'webpack' ); | ||
const json2php = require( 'json2php' ); | ||
const { createHash } = webpack.util; | ||
|
||
const { RawSource } = webpack.sources; | ||
const { AsyncDependenciesBlock } = webpack; | ||
|
||
class AssetDataPlugin { | ||
constructor( options ) { | ||
this.options = Object.assign( | ||
{ | ||
combineAssets: false, | ||
combinedOutputFile: null, | ||
outputFormat: 'php', | ||
outputFilename: null, | ||
}, | ||
options | ||
); | ||
} | ||
|
||
/** | ||
* @param {any} asset Asset Data | ||
* @return {string} Stringified asset data suitable for output | ||
*/ | ||
stringify( asset ) { | ||
if ( this.options.outputFormat === 'php' ) { | ||
return `<?php return ${ json2php( | ||
JSON.parse( JSON.stringify( asset ) ) | ||
) };\n`; | ||
} | ||
|
||
return JSON.stringify( asset ); | ||
} | ||
|
||
apply( compiler ) { | ||
compiler.hooks.thisCompilation.tap( | ||
this.constructor.name, | ||
( compilation ) => { | ||
compilation.hooks.processAssets.tap( | ||
{ | ||
name: this.constructor.name, | ||
stage: compiler.webpack.Compilation | ||
.PROCESS_ASSETS_STAGE_ANALYSE, | ||
}, | ||
() => this.addAssets( compilation ) | ||
); | ||
} | ||
); | ||
} | ||
|
||
/** @param {webpack.Compilation} compilation */ | ||
addAssets( compilation ) { | ||
const { | ||
combineAssets, | ||
combinedOutputFile, | ||
outputFormat, | ||
outputFilename, | ||
} = this.options; | ||
|
||
const combinedAssetsData = {}; | ||
|
||
// 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 styleExtensionRegExp = /\.s?css$/i; | ||
|
||
const chunkStyleFile = chunkFiles.find( ( f ) => | ||
styleExtensionRegExp.test( f ) | ||
); | ||
if ( ! chunkStyleFile ) { | ||
// No style file, skip | ||
continue; | ||
} | ||
|
||
// Go through the assets and hash the sources. We can't just use | ||
// `chunk.contentHash` because that's not updated when | ||
// assets are minified. In practice the hash is updated by | ||
// `RealContentHashPlugin` after minification, but it only modifies | ||
// already-produced asset filenames and the updated hash is not | ||
// available to plugins. | ||
const { hashFunction, hashDigest, hashDigestLength } = | ||
compilation.outputOptions; | ||
|
||
const contentHash = chunkFiles | ||
.sort() | ||
.reduce( ( hash, filename ) => { | ||
const asset = compilation.getAsset( filename ); | ||
return hash.update( asset.source.buffer() ); | ||
}, createHash( hashFunction ) ) | ||
.digest( hashDigest ) | ||
.slice( 0, hashDigestLength ); | ||
|
||
const assetData = { | ||
version: contentHash, | ||
}; | ||
|
||
if ( combineAssets ) { | ||
combinedAssetsData[ chunkStyleFile ] = assetData; | ||
continue; | ||
} | ||
|
||
let assetFilename; | ||
if ( outputFilename ) { | ||
assetFilename = compilation.getPath( outputFilename, { | ||
chunk, | ||
filename: chunkStyleFile, | ||
contentHash, | ||
} ); | ||
} else { | ||
const suffix = | ||
'.asset.' + ( outputFormat === 'php' ? 'php' : 'json' ); | ||
assetFilename = compilation | ||
.getPath( '[file]', { filename: chunkStyleFile } ) | ||
.replace( styleExtensionRegExp, suffix ); | ||
} | ||
|
||
// Add source and file into compilation for webpack to output. | ||
compilation.assets[ assetFilename ] = new RawSource( | ||
this.stringify( assetData ) | ||
); | ||
chunk.files.add( assetFilename ); | ||
} | ||
|
||
if ( combineAssets ) { | ||
const outputFolder = compilation.outputOptions.path; | ||
|
||
const assetsFilePath = path.resolve( | ||
outputFolder, | ||
combinedOutputFile || | ||
'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 ) | ||
); | ||
} | ||
} | ||
|
||
/** | ||
* Can we trace a line of static dependencies from an entry to a module | ||
* | ||
* @param {webpack.Compilation} compilation | ||
* @param {webpack.DependenciesBlock} block | ||
* | ||
* @return {boolean} True if there is a static import path to the root | ||
*/ | ||
static hasStaticDependencyPathToRoot( compilation, block ) { | ||
const incomingConnections = [ | ||
...compilation.moduleGraph.getIncomingConnections( block ), | ||
].filter( | ||
( connection ) => | ||
// Library connections don't have a dependency, this is a root | ||
connection.dependency && | ||
// Entry dependencies are another root | ||
connection.dependency.constructor.name !== 'EntryDependency' | ||
); | ||
|
||
// If we don't have non-entry, non-library incoming connections, | ||
// we've reached a root of | ||
if ( ! incomingConnections.length ) { | ||
return true; | ||
} | ||
|
||
const staticDependentModules = incomingConnections.flatMap( | ||
( connection ) => { | ||
const { dependency } = connection; | ||
const parentBlock = | ||
compilation.moduleGraph.getParentBlock( dependency ); | ||
|
||
return parentBlock.constructor.name !== | ||
AsyncDependenciesBlock.name | ||
? [ compilation.moduleGraph.getParentModule( dependency ) ] | ||
: []; | ||
} | ||
); | ||
|
||
// All the dependencies were Async, the module was reached via a dynamic import | ||
if ( ! staticDependentModules.length ) { | ||
return false; | ||
} | ||
|
||
// Continue to explore any static dependencies | ||
return staticDependentModules.some( ( parentStaticDependentModule ) => | ||
AssetDataPlugin.hasStaticDependencyPathToRoot( | ||
compilation, | ||
parentStaticDependentModule | ||
) | ||
); | ||
} | ||
} | ||
|
||
module.exports = AssetDataPlugin; |
4 changes: 4 additions & 0 deletions
4
packages/js/product-editor/changelog/44838-dev-use-content-hash
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Significance: patch | ||
Type: dev | ||
|
||
Improve webpack cache-busting version parameter by using file contents hash |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Significance: patch | ||
Type: dev | ||
|
||
Improve webpack cache-busting version parameter by using file contents hash |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like a great upstream contribution. If I'm reading correctly, you've inserted logic to find CSS files in the loop over
entrypointChunks
and assigned a content hash, similar to the one used for JS.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct! And I also removed some unnecessary extraction logic. 🙂