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
Conversation
WCAdminAssets::get_file_version( 'css' ) | ||
); | ||
|
||
WCAdminAssets::register_script( 'wp-admin-scripts', 'payment-method-promotions', true ); |
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.
This shouldn't be called in the constructor as it will be called multiple times. Additionally, observing it in watch dev mode sometimes results in errors.
[21-Feb-2024 07:09:48 UTC] PHP Fatal error: Uncaught Exception: Could not find asset registry for wp-admin-scripts in /Users/chihsuan/Projects/woocommerce/plugins/woocommerce/src/Internal/Admin/WCAdminAssets.php:136
Stack trace:
#0 /Users/chihsuan/Projects/woocommerce/plugins/woocommerce/src/Internal/Admin/WCAdminAssets.php(471): Automattic\WooCommerce\Internal\Admin\WCAdminAssets::get_script_asset_filename('wp-admin-script...', 'payment-method-...')
#1 /Users/chihsuan/Projects/woocommerce/plugins/woocommerce/src/Internal/Admin/WCPayPromotion/Init.php(44): Automattic\WooCommerce\Internal\Admin\WCAdminAssets::register_script('wp-admin-script...', 'payment-method-...', true)
#2 /Users/chihsuan/Projects/woocommerce/plugins/woocommerce/src/Admin/Features/Features.php(138): Automattic\WooCommerce\Internal\Admin\WCPayPromotion\Init->__construct()
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.
Good catch!
Test Results SummaryCommit SHA: 595e99f
To view the full API test report, click here. To view the full E2E test report, click here. To view all test reports, visit the WooCommerce Test Reports Dashboard. |
Hi @psealock, @ilyasfoo, @woocommerce/mothra Apart from reviewing the code changes, please make sure to review the testing instructions as well. You can follow this guide to find out what good testing instructions should look like: |
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.
nice work @chihsuan!
Just a couple comments and questions. And I am curious if this would be a better upstream contribution because it means less for Woo to maintain. Can Style Asset Plugin remain if the addition of CSS gets merged upstream directly to Dep Extraction Webpack Plugin? If so, we can merge this with a comment to safely remove once upstream changes materialise.
* | ||
* This is modified from WP dependency-extraction-webpack-plugin plugin: | ||
* https://github.com/WordPress/gutenberg/tree/a04a8e94e8b93ba60441c6534e21f4c3c26ff1bc/packages/dependency-extraction-webpack-plugin | ||
*/ |
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.
To support CSS files, I added a new plugin called style-asset-plugin to extract the CSS file hash and write it to the asset manifest file. It's just a simple modification of the dependency-extraction-webpack-plugin.
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. 🙂
*/ | ||
public static function register_style( $style_path_name, $style_name, $dependencies = array() ) { | ||
$style_assets_filename = self::get_script_asset_filename( $style_path_name, $style_name ); | ||
$style_assets = require WC_ADMIN_ABSPATH . WC_ADMIN_DIST_JS_FOLDER . $style_path_name . '/' . $style_assets_filename; |
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.
This is working, but I'm wondering why this wouldn't use WC_ADMIN_DIST_CSS_FOLDER
instead of the JS one?
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.
They are now one and the same! This would be a good opportunity to clean that up.
woocommerce/plugins/woocommerce/src/Internal/Admin/FeaturePlugin.php
Lines 107 to 108 in be4a365
$this->define( 'WC_ADMIN_DIST_JS_FOLDER', 'assets/client/admin/' ); | |
$this->define( 'WC_ADMIN_DIST_CSS_FOLDER', 'assets/client/admin/' ); |
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.
Thanks for brining this up! Do you have any suggestions? I think even though they are the same, maintaining two variables can provide flexibility.
I will change register_style
to use WC_ADMIN_DIST_CSS_FOLDER
.
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.
Changed to use WC_ADMIN_DIST_CSS_FOLDER
in 1c0d6c6
WCAdminAssets::get_file_version( 'css' ) | ||
); | ||
|
||
WCAdminAssets::register_style( 'print-shipping-label-banner', 'style', array( 'wp-components' ) ); |
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.
This will be renaming the script to wc-admin-print-shipping-label-banner
, I'm pretty sure nothing depends on this script, but it would be good to go through and double check we aren't renaming anything in this PR that isn't being depended on elsewhere in Core or otherwise out in the wild.
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.
Thanks for the heads up!
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.
I've double-checked, and only this script is renamed in this PR and also confirmed that those scripts are loaded properly, so we should be good to go.
@psealock Yes, good idea. 👍 It should be possible to contribute upstream. I'll create a follow-up issue and add a comment to the Style Asset plugin. Edit: Issue created: https://github.com/woocommerce/team-ghidorah/issues/288 |
9af91a1
to
fcdeed1
Compare
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.
@chihsuan I'm think the following is caused by this PR, when I ran pnpm run --filter @woocommerce/plugin-woocommerce watch:build
, waited it to complete, then make changes to plugins/woocommerce-admin/client/homescreen/index.tsx
, it crashes:
../woocommerce-admin watch:build:project:bundle: webpack 5.89.0 compiled successfully in 9223 ms
. watch:build:project:copy-assets: 0% [0 / 1] [0 running]
../woocommerce-admin watch:build:project:bundle: No errors found.
. watch:build:project:copy-assets: 0% [0 / 1] [1 running] build:project:copy-assets
. watch:build:project:copy-assets: ✅ Ran 1 script and skipped 0 in 2.3s.
. watch:build:project:copy-assets: [nodemon] clean exit - waiting for changes before restart
. watch:build:project:copy-assets: [nodemon] restarting due to changes...
. watch:build:project:copy-assets: [nodemon] starting `pnpm run build:project`
. watch:build:project:copy-assets: > @woocommerce/plugin-woocommerce@8.7.0 build:project [redacted]/woocommerce/plugins/woocommerce
. watch:build:project:copy-assets: > pnpm --if-present '/^build:project:.*$/'
../woocommerce-admin watch:build:project:bundle: [webpack-cli] Error: Prevent writing to file that only differs in casing or query string from already written file.
../woocommerce-admin watch:build:project:bundle: This will lead to a race-condition and corrupted files on case-insensitive file systems.
../woocommerce-admin watch:build:project:bundle: [redacted]/woocommerce/plugins/woocommerce-admin/build/chunks/homescreen.js
../woocommerce-admin watch:build:project:bundle: [redacted]/woocommerce/plugins/woocommerce-admin/build/chunks/homescreen.js
../woocommerce-admin watch:build:project:bundle: at checkSimilarFile ([redacted]/woocommerce/node_modules/.pnpm/webpack@5.89.0_webpack-cli@4.10.0/node_modules/webpack/lib/Compiler.js:666:11)
../woocommerce-admin watch:build:project:bundle: at writeOut ([redacted]/woocommerce/node_modules/.pnpm/webpack@5.89.0_webpack-cli@4.10.0/node_modules/webpack/lib/Compiler.js:840:13)
../woocommerce-admin watch:build:project:bundle: at [redacted]/woocommerce/node_modules/.pnpm/webpack@5.89.0_webpack-cli@4.10.0/node_modules/webpack/lib/util/fs.js:242:5
../woocommerce-admin watch:build:project:bundle: at FSReqCallback.oncomplete (node:fs:196:23)
. watch:build:project:copy-assets: > @woocommerce/plugin-woocommerce@8.7.0 build:project:copy-assets [redacted]/woocommerce/plugins/woocommerce
. watch:build:project:copy-assets: > wireit
../woocommerce-admin watch:build:project:bundle: Error: write EPIPE
../woocommerce-admin watch:build:project:bundle: at process.target._send (node:internal/child_process:867:20)
../woocommerce-admin watch:build:project:bundle: at process.target.send (node:internal/child_process:740:19)
../woocommerce-admin watch:build:project:bundle: at [redacted]/woocommerce/node_modules/.pnpm/fork-ts-checker-webpack-plugin@8.0.0_typescript@5.3.3_webpack@5.89.0/node_modules/fork-ts-checker-webpack-plugin/lib/rpc/expose-rpc.js:27:31
../woocommerce-admin watch:build:project:bundle: at new Promise (<anonymous>)
../woocommerce-admin watch:build:project:bundle: at sendMessage ([redacted]/woocommerce/node_modules/.pnpm/fork-ts-checker-webpack-plugin@8.0.0_typescript@5.3.3_webpack@5.89.0/node_modules/fork-ts-checker-webpack-plugin/lib/rpc/expose-rpc.js:19:38)
../woocommerce-admin watch:build:project:bundle: at [redacted]/woocommerce/node_modules/.pnpm/fork-ts-checker-webpack-plugin@8.0.0_typescript@5.3.3_webpack@5.89.0/node_modules/fork-ts-checker-webpack-plugin/lib/rpc/expose-rpc.js:60:27
../woocommerce-admin watch:build:project:bundle: at Generator.next (<anonymous>)
../woocommerce-admin watch:build:project:bundle: at fulfilled ([redacted]/woocommerce/node_modules/.pnpm/fork-ts-checker-webpack-plugin@8.0.0_typescript@5.3.3_webpack@5.89.0/node_modules/fork-ts-checker-webpack-plugin/lib/rpc/expose-rpc.js:5:58) {
../woocommerce-admin watch:build:project:bundle: errno: -32,
../woocommerce-admin watch:build:project:bundle: code: 'EPIPE',
../woocommerce-admin watch:build:project:bundle: syscall: 'write'
../woocommerce-admin watch:build:project:bundle: }
../woocommerce-admin watch:build:project:bundle: ❌ [watch:build:project:bundle] Service exited unexpectedly
../woocommerce-admin watch:build:project:bundle: ❌ 1 script failed.
../woocommerce-admin watch:build:project:bundle: Failed
[redacted]/woocommerce/plugins/woocommerce-admin:
ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL @woocommerce/admin-library@3.3.0 watch:build:project:bundle: `wireit`
Exit status 1
. watch:build:project:copy-assets: Analyzing
[redacted]/woocommerce/plugins/woocommerce:
ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL @woocommerce/plugin-woocommerce@8.7.0 watch:build: `pnpm --if-present --workspace-concurrency=Infinity --filter="$npm_package_name..." --parallel '/^watch:build:project:.*$/'`
Exit status 1
Good catch! @ilyasfoo It turns out there's a bug in |
0c4688d
to
dfd38e3
Compare
aeffba1
to
0a1ea1b
Compare
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.
WCAdminAssets::get_file_version( 'css' ) | ||
); | ||
|
||
WCAdminAssets::register_script( 'wp-admin-scripts', 'payment-method-promotions', true ); |
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.
Good catch!
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.
Yes, this is intended. Some are legacy assets as Paul mentioned and some are chunks that can't be enqueued via PHP. |
…e asset php for styles
- Use file hash to load scripts/styles ?ver=<file hash> - Add register_style() method to WC_Admin_Assets
…ommerce/product-editor, woocommerce
0a1ea1b
to
5591fcb
Compare
…s hash (#44838) * Update webpack config to use file content hash for chunks and generate asset php for styles * Use StyleAssetPlugin to generate style.asset.php * Remove unneed ?ver=<version> code * Use file hash from asset file when SCRIPT_DEBUG is off - Use file hash to load scripts/styles ?ver=<file hash> - Add register_style() method to WC_Admin_Assets * Load payment method promotions in admin_enqueue_scripts * Add changefile(s) from automation for the following project(s): @woocommerce/product-editor, woocommerce * Add json2php * Update doc * Update pnpm-lock.yaml * Fix add_print_shipping_label_script * Add a comment to style-asset-plugin.js * Change register_style to use WC_ADMIN_DIST_CSS_FOLDER * Reset the outputNormal object to avoid duplicate files * Fix type error --------- Co-authored-by: github-actions <github-actions@github.com>
Submission Review Guidelines:
Changes proposed in this Pull Request:
Closes #33337
This PR improves the cache-busting version parameter by using
?ver=<file hash>
instead of a version number, which makes it so that the client does not have to re-fetch resources that haven't changed recently.There are two kinds of resources, one is scripts that are enqueued in PHP, and the other is chunks that are generated by webpack and loaded in the frontend.
For the former, the version parameter is added to the URL by the
wp_enqueue_script
function, we uses theversion
from the asset manifest file to get the file hash. It's possible to get file hash dynamically but it may affect performance, so I chose to use the asset manifest file. The approach is also used to load wp-includes scripts in WP core.For the latter, we simply change the
output
config inwebpack.config.js
to load the file with the hash.The asset manifest file is generated by the dependency-extraction-webpack-plugin and contains the unique version hash calculated based on the file content. However, it only supports JS files. To support CSS files, I added a new plugin called
style-asset-plugin
to extract the CSS file hash and write it to the asset manifest file. It's just a simple modification of thedependency-extraction-webpack-plugin
.Please note that because the asset file is not regenerated in Webpack watch mode, you need to run
pnpm build
to get the new hash and whenSCRIPT_DEBUG
is enabled, the version parameter is replaced with file modified time.How to test the changes in this Pull Request:
Using the WooCommerce Testing Instructions Guide, include your detailed testing instructions:
define( 'SCRIPT_DEBUG', false );
in your wp-config.php file.?ver=<hash>
is set on all WooCommerce Admin JS and CSS requests, please ignore assets loaded from/assets/
path since we're not able to use webpack to get file hash.plugins/woocommerce-admin/client/app.js
(add a console.log for example)pnpm run --filter @woocommerce/plugin-woocommerce build
<hash>
value is changed/wp-admin/admin.php?page=wc-settings&tab=checkout
payment-method-promotions.js
script is loaded properly likepayment-method-promotions.js?ver=5a20ddfd6fe486acf2ba
.define( 'SCRIPT_DEBUG', true );
in your wp-config.php file.?ver=<timestamp>
is set on all WooCommerce Admin JS and CSS requests (Ignore legacy assets from/assets/
path and/chunks
)When
SCRIPT_DEBUG
is enabled:Changelog entry
Significance
Type
Message
Improve webpack cache-busting version parameter by using file contents hash
Comment