Improve webpack cache-busting version parameter by using file contents 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>
This commit is contained in:
parent
707c555091
commit
ec8bd31365
|
@ -6,6 +6,7 @@ const path = require( 'path' );
|
||||||
const WebpackRTLPlugin = require( 'webpack-rtl-plugin' );
|
const WebpackRTLPlugin = require( 'webpack-rtl-plugin' );
|
||||||
const RemoveEmptyScriptsPlugin = require( 'webpack-remove-empty-scripts' );
|
const RemoveEmptyScriptsPlugin = require( 'webpack-remove-empty-scripts' );
|
||||||
const postcssPlugins = require( '@wordpress/postcss-plugins-preset' );
|
const postcssPlugins = require( '@wordpress/postcss-plugins-preset' );
|
||||||
|
const StyleAssetPlugin = require( './style-asset-plugin' );
|
||||||
|
|
||||||
const NODE_ENV = process.env.NODE_ENV || 'development';
|
const NODE_ENV = process.env.NODE_ENV || 'development';
|
||||||
|
|
||||||
|
@ -69,12 +70,14 @@ module.exports = {
|
||||||
new RemoveEmptyScriptsPlugin(),
|
new RemoveEmptyScriptsPlugin(),
|
||||||
new MiniCssExtractPlugin( {
|
new MiniCssExtractPlugin( {
|
||||||
filename: '[name]/style.css',
|
filename: '[name]/style.css',
|
||||||
chunkFilename: 'chunks/[id].style.css',
|
chunkFilename: 'chunks/[id].style.css?ver=[contenthash]',
|
||||||
} ),
|
} ),
|
||||||
new WebpackRTLPlugin( {
|
new WebpackRTLPlugin( {
|
||||||
filename: '[name]/style-rtl.css',
|
filename: '[name]/style-rtl.css',
|
||||||
minify: NODE_ENV === 'development' ? false : { safe: true },
|
minify: NODE_ENV === 'development' ? false : { safe: true },
|
||||||
} ),
|
} ),
|
||||||
|
new StyleAssetPlugin(),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
StyleAssetPlugin,
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
"@wordpress/base-styles": "wp-6.0",
|
"@wordpress/base-styles": "wp-6.0",
|
||||||
"@wordpress/postcss-plugins-preset": "wp-6.0",
|
"@wordpress/postcss-plugins-preset": "wp-6.0",
|
||||||
"css-loader": "^3.6.0",
|
"css-loader": "^3.6.0",
|
||||||
|
"json2php": "^0.0.7",
|
||||||
"mini-css-extract-plugin": "^2.7.6",
|
"mini-css-extract-plugin": "^2.7.6",
|
||||||
"postcss-loader": "^4.3.0",
|
"postcss-loader": "^4.3.0",
|
||||||
"sass-loader": "^10.5.0",
|
"sass-loader": "^10.5.0",
|
||||||
|
|
|
@ -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;
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: dev
|
||||||
|
|
||||||
|
Improve webpack cache-busting version parameter by using file contents hash
|
|
@ -10,7 +10,10 @@ const WebpackRTLPlugin = require( 'webpack-rtl-plugin' );
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
const { webpackConfig } = require( '@woocommerce/internal-style-build' );
|
const {
|
||||||
|
webpackConfig,
|
||||||
|
StyleAssetPlugin,
|
||||||
|
} = require( '@woocommerce/internal-style-build' );
|
||||||
const {
|
const {
|
||||||
blockEntryPoints,
|
blockEntryPoints,
|
||||||
getBlockMetaData,
|
getBlockMetaData,
|
||||||
|
@ -69,5 +72,6 @@ module.exports = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} ),
|
} ),
|
||||||
|
new StyleAssetPlugin(),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,29 +21,6 @@ import { WcAdminConflictErrorSlot } from './settings/conflict-error-slotfill.js'
|
||||||
import './xstate.js';
|
import './xstate.js';
|
||||||
import { deriveWpAdminBackgroundColours } from './utils/derive-wp-admin-background-colours';
|
import { deriveWpAdminBackgroundColours } from './utils/derive-wp-admin-background-colours';
|
||||||
|
|
||||||
// Modify webpack pubilcPath at runtime based on location of WordPress Plugin.
|
|
||||||
// eslint-disable-next-line no-undef,camelcase
|
|
||||||
__webpack_public_path__ = global.wcAdminAssets.path;
|
|
||||||
|
|
||||||
// Modify webpack to append the ?ver parameter to JS chunk
|
|
||||||
// https://webpack.js.org/api/module-variables/#__webpack_get_script_filename__-webpack-specific
|
|
||||||
// eslint-disable-next-line no-undef,camelcase
|
|
||||||
const oldGetScriptFileNameFn = __webpack_get_script_filename__;
|
|
||||||
// eslint-disable-next-line no-undef,camelcase
|
|
||||||
__webpack_get_script_filename__ = ( chunk ) => {
|
|
||||||
const filename = oldGetScriptFileNameFn( chunk );
|
|
||||||
return `${ filename }?ver=${ window.wcAdminAssets.version }`;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Modify webpack to append the ?ver parameter to CSS chunk hrefs generated by mini-css-extract-plugin
|
|
||||||
// eslint-disable-next-line no-undef,camelcase
|
|
||||||
const oldMinCssFn = __webpack_require__.miniCssF;
|
|
||||||
// eslint-disable-next-line no-undef,camelcase
|
|
||||||
__webpack_require__.miniCssF = ( chunkId ) => {
|
|
||||||
const filename = oldMinCssFn( chunkId );
|
|
||||||
return `${ filename }?ver=${ window.wcAdminAssets.version }`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const appRoot = document.getElementById( 'root' );
|
const appRoot = document.getElementById( 'root' );
|
||||||
const embeddedRoot = document.getElementById( 'woocommerce-embedded-root' );
|
const embeddedRoot = document.getElementById( 'woocommerce-embedded-root' );
|
||||||
const settingsGroup = 'wc_admin';
|
const settingsGroup = 'wc_admin';
|
||||||
|
|
|
@ -39,7 +39,7 @@ class UnminifyWebpackPlugin {
|
||||||
|
|
||||||
apply( compiler ) {
|
apply( compiler ) {
|
||||||
const options = this.options;
|
const options = this.options;
|
||||||
const outputNormal = {};
|
let outputNormal = {};
|
||||||
|
|
||||||
compiler.hooks.compilation.tap(
|
compiler.hooks.compilation.tap(
|
||||||
'UnminifyWebpackPlugin',
|
'UnminifyWebpackPlugin',
|
||||||
|
@ -107,6 +107,8 @@ class UnminifyWebpackPlugin {
|
||||||
value.filename,
|
value.filename,
|
||||||
new webpack.sources.RawSource( value.content )
|
new webpack.sources.RawSource( value.content )
|
||||||
);
|
);
|
||||||
|
// Reset the outputNormal object to avoid writing to file that only differs in casing or query string from already written file.
|
||||||
|
outputNormal = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -101,7 +101,7 @@ const webpackConfig = {
|
||||||
? `wp-admin-scripts/[name]${ outputSuffix }.js`
|
? `wp-admin-scripts/[name]${ outputSuffix }.js`
|
||||||
: `[name]/index${ outputSuffix }.js`;
|
: `[name]/index${ outputSuffix }.js`;
|
||||||
},
|
},
|
||||||
chunkFilename: `chunks/[name]${ outputSuffix }.js`,
|
chunkFilename: `chunks/[name]${ outputSuffix }.js?ver=[contenthash]`,
|
||||||
path: path.join( __dirname, '/build' ),
|
path: path.join( __dirname, '/build' ),
|
||||||
library: {
|
library: {
|
||||||
// Expose the exports of entry points so we can consume the libraries in window.wc.[modulename] with WooCommerceDependencyExtractionWebpackPlugin.
|
// Expose the exports of entry points so we can consume the libraries in window.wc.[modulename] with WooCommerceDependencyExtractionWebpackPlugin.
|
||||||
|
@ -200,7 +200,8 @@ const webpackConfig = {
|
||||||
// The package build process doesn't handle extracting CSS from JS files, so we copy them separately.
|
// The package build process doesn't handle extracting CSS from JS files, so we copy them separately.
|
||||||
new CopyWebpackPlugin( {
|
new CopyWebpackPlugin( {
|
||||||
patterns: wcAdminPackages.map( ( packageName ) => ( {
|
patterns: wcAdminPackages.map( ( packageName ) => ( {
|
||||||
from: `../../packages/js/${ packageName }/build-style/*.css`,
|
// Copy css and style.asset.php files.
|
||||||
|
from: `../../packages/js/${ packageName }/build-style/*.{css,php}`,
|
||||||
to: `./${ packageName }/[name][ext]`,
|
to: `./${ packageName }/[name][ext]`,
|
||||||
noErrorOnMissing: true,
|
noErrorOnMissing: true,
|
||||||
// Overwrites files already in compilation.assets to ensure we use the assets from the build-style.
|
// Overwrites files already in compilation.assets to ensure we use the assets from the build-style.
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: dev
|
||||||
|
|
||||||
|
Improve webpack cache-busting version parameter by using file contents hash
|
|
@ -586,7 +586,7 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) :
|
||||||
'wc-admin-' . $script_name,
|
'wc-admin-' . $script_name,
|
||||||
WCAdminAssets::get_url( $script_path_name . '/' . $script_name, 'js' ),
|
WCAdminAssets::get_url( $script_path_name . '/' . $script_name, 'js' ),
|
||||||
$script_assets['dependencies'],
|
$script_assets['dependencies'],
|
||||||
WCAdminAssets::get_file_version( 'js' ),
|
WCAdminAssets::get_file_version( 'js', $script_assets['version'] ),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ class Features {
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function get_optional_feature_options() {
|
public static function get_optional_feature_options() {
|
||||||
$features = [];
|
$features = array();
|
||||||
|
|
||||||
foreach ( array_keys( self::$optional_features ) as $optional_feature_key ) {
|
foreach ( array_keys( self::$optional_features ) as $optional_feature_key ) {
|
||||||
$feature_class = self::get_feature_class( $optional_feature_key );
|
$feature_class = self::get_feature_class( $optional_feature_key );
|
||||||
|
@ -148,7 +148,7 @@ class Features {
|
||||||
public static function get_available_features() {
|
public static function get_available_features() {
|
||||||
$features = self::get_features();
|
$features = self::get_features();
|
||||||
$optional_feature_keys = array_keys( self::$optional_features );
|
$optional_feature_keys = array_keys( self::$optional_features );
|
||||||
$optional_features_unavailable = [];
|
$optional_features_unavailable = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter allowing WooCommerce Admin optional features to be disabled.
|
* Filter allowing WooCommerce Admin optional features to be disabled.
|
||||||
|
@ -292,22 +292,8 @@ class Features {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$rtl = is_rtl() ? '.rtl' : '';
|
WCAdminAssets::register_style( 'beta-features-tracking-modal', 'style', array( 'wp-components' ) );
|
||||||
|
WCAdminAssets::register_script( 'wp-admin-scripts', 'beta-features-tracking-modal', array( 'wp-i18n', 'wp-element', WC_ADMIN_APP ) );
|
||||||
wp_enqueue_style(
|
|
||||||
'wc-admin-beta-features-tracking-modal',
|
|
||||||
WCAdminAssets::get_url( "beta-features-tracking-modal/style{$rtl}", 'css' ),
|
|
||||||
array( 'wp-components' ),
|
|
||||||
WCAdminAssets::get_file_version( 'css' )
|
|
||||||
);
|
|
||||||
|
|
||||||
wp_enqueue_script(
|
|
||||||
'wc-admin-beta-features-tracking-modal',
|
|
||||||
WCAdminAssets::get_url( 'wp-admin-scripts/beta-features-tracking-modal', 'js' ),
|
|
||||||
array( 'wp-i18n', 'wp-element', WC_ADMIN_APP ),
|
|
||||||
WCAdminAssets::get_file_version( 'js' ),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -123,14 +123,7 @@ class Init {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$rtl = is_rtl() ? '.rtl' : '';
|
WCAdminAssets::register_style( 'navigation-opt-out', 'style', array( 'wp-components' ) );
|
||||||
wp_enqueue_style(
|
|
||||||
'wc-admin-navigation-opt-out',
|
|
||||||
WCAdminAssets::get_url( "navigation-opt-out/style{$rtl}", 'css' ),
|
|
||||||
array( 'wp-components' ),
|
|
||||||
WCAdminAssets::get_file_version( 'css' )
|
|
||||||
);
|
|
||||||
|
|
||||||
WCAdminAssets::register_script( 'wp-admin-scripts', 'navigation-opt-out', true );
|
WCAdminAssets::register_script( 'wp-admin-scripts', 'navigation-opt-out', true );
|
||||||
wp_localize_script(
|
wp_localize_script(
|
||||||
'wc-admin-navigation-opt-out',
|
'wc-admin-navigation-opt-out',
|
||||||
|
|
|
@ -73,7 +73,7 @@ class Coupons {
|
||||||
__( 'Coupons', 'woocommerce' ),
|
__( 'Coupons', 'woocommerce' ),
|
||||||
'manage_options',
|
'manage_options',
|
||||||
'coupons-moved',
|
'coupons-moved',
|
||||||
[ $this, 'coupon_menu_moved' ]
|
array( $this, 'coupon_menu_moved' )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,15 +117,7 @@ class Coupons {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$rtl = is_rtl() ? '-rtl' : '';
|
WCAdminAssets::register_style( 'marketing-coupons', 'style' );
|
||||||
|
|
||||||
wp_enqueue_style(
|
|
||||||
'wc-admin-marketing-coupons',
|
|
||||||
WCAdminAssets::get_url( "marketing-coupons/style{$rtl}", 'css' ),
|
|
||||||
array(),
|
|
||||||
WCAdminAssets::get_file_version( 'css' )
|
|
||||||
);
|
|
||||||
|
|
||||||
WCAdminAssets::register_script( 'wp-admin-scripts', 'marketing-coupons', true );
|
WCAdminAssets::register_script( 'wp-admin-scripts', 'marketing-coupons', true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,14 +128,7 @@ class ShippingLabelBanner {
|
||||||
* @param string $hook current page hook.
|
* @param string $hook current page hook.
|
||||||
*/
|
*/
|
||||||
public function add_print_shipping_label_script( $hook ) {
|
public function add_print_shipping_label_script( $hook ) {
|
||||||
$rtl = is_rtl() ? '.rtl' : '';
|
WCAdminAssets::register_style( 'print-shipping-label-banner', 'style', array( 'wp-components' ) );
|
||||||
wp_enqueue_style(
|
|
||||||
'print-shipping-label-banner-style',
|
|
||||||
WCAdminAssets::get_url( "print-shipping-label-banner/style{$rtl}", 'css' ),
|
|
||||||
array( 'wp-components' ),
|
|
||||||
WCAdminAssets::get_file_version( 'css' )
|
|
||||||
);
|
|
||||||
|
|
||||||
WCAdminAssets::register_script( 'wp-admin-scripts', 'print-shipping-label-banner', true );
|
WCAdminAssets::register_script( 'wp-admin-scripts', 'print-shipping-label-banner', true );
|
||||||
|
|
||||||
$payload = array(
|
$payload = array(
|
||||||
|
|
|
@ -98,15 +98,22 @@ class WCAdminAssets {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the file modified time as a cache buster if we're in dev mode, or the plugin version otherwise.
|
* Gets the file modified time as a cache buster if we're in dev mode,
|
||||||
|
* or the asset version (file content hash) if exists, or the WooCommerce version.
|
||||||
*
|
*
|
||||||
* @param string $ext File extension.
|
* @param string $ext File extension.
|
||||||
|
* @param string|null $asset_version Optional. The version from the asset file.
|
||||||
* @return string The cache buster value to use for the given file.
|
* @return string The cache buster value to use for the given file.
|
||||||
*/
|
*/
|
||||||
public static function get_file_version( $ext ) {
|
public static function get_file_version( $ext, $asset_version = null ) {
|
||||||
if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
|
if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
|
||||||
return filemtime( WC_ADMIN_ABSPATH . self::get_path( $ext ) );
|
return filemtime( WC_ADMIN_ABSPATH . self::get_path( $ext ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( ! empty( $asset_version ) ) {
|
||||||
|
return $asset_version;
|
||||||
|
}
|
||||||
|
|
||||||
return WC_VERSION;
|
return WC_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,9 +260,7 @@ class WCAdminAssets {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$js_file_version = self::get_file_version( 'js' );
|
// Register the JS scripts.
|
||||||
$css_file_version = self::get_file_version( 'css' );
|
|
||||||
|
|
||||||
$scripts = array(
|
$scripts = array(
|
||||||
'wc-admin-layout',
|
'wc-admin-layout',
|
||||||
'wc-explat',
|
'wc-explat',
|
||||||
|
@ -299,6 +304,7 @@ class WCAdminAssets {
|
||||||
try {
|
try {
|
||||||
$script_assets_filename = self::get_script_asset_filename( $script_path_name, 'index' );
|
$script_assets_filename = self::get_script_asset_filename( $script_path_name, 'index' );
|
||||||
$script_assets = require WC_ADMIN_ABSPATH . WC_ADMIN_DIST_JS_FOLDER . $script_path_name . '/' . $script_assets_filename;
|
$script_assets = require WC_ADMIN_ABSPATH . WC_ADMIN_DIST_JS_FOLDER . $script_path_name . '/' . $script_assets_filename;
|
||||||
|
$script_version = self::get_file_version( 'js', $script_assets['version'] );
|
||||||
|
|
||||||
global $wp_version;
|
global $wp_version;
|
||||||
if ( 'app' === $script_path_name && version_compare( $wp_version, '6.3', '<' ) ) {
|
if ( 'app' === $script_path_name && version_compare( $wp_version, '6.3', '<' ) ) {
|
||||||
|
@ -320,92 +326,83 @@ class WCAdminAssets {
|
||||||
wp_register_script(
|
wp_register_script(
|
||||||
$script,
|
$script,
|
||||||
self::get_url( $script_path_name . '/index', 'js' ),
|
self::get_url( $script_path_name . '/index', 'js' ),
|
||||||
$script_assets ['dependencies'],
|
$script_assets['dependencies'],
|
||||||
$js_file_version,
|
$script_version,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( in_array( $script, $translated_scripts, true ) ) {
|
if ( in_array( $script, $translated_scripts, true ) ) {
|
||||||
wp_set_script_translations( $script, 'woocommerce' );
|
wp_set_script_translations( $script, 'woocommerce' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( WC_ADMIN_APP === $script ) {
|
||||||
|
wp_localize_script(
|
||||||
|
WC_ADMIN_APP,
|
||||||
|
'wcAdminAssets',
|
||||||
|
array(
|
||||||
|
'path' => plugins_url( self::get_path( 'js' ), WC_ADMIN_PLUGIN_FILE ),
|
||||||
|
'version' => $script_version,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
} catch ( \Exception $e ) {
|
} catch ( \Exception $e ) {
|
||||||
// Avoid crashing WordPress if an asset file could not be loaded.
|
// Avoid crashing WordPress if an asset file could not be loaded.
|
||||||
wc_caught_exception( $e, __CLASS__ . '::' . __FUNCTION__, $script_path_name );
|
wc_caught_exception( $e, __CLASS__ . '::' . __FUNCTION__, $script_path_name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wp_register_style(
|
// Register the CSS styles.
|
||||||
'wc-admin-layout',
|
$styles = array(
|
||||||
self::get_url( 'admin-layout/style', 'css' ),
|
|
||||||
array(),
|
|
||||||
$css_file_version
|
|
||||||
);
|
|
||||||
wp_style_add_data( 'wc-admin-layout', 'rtl', 'replace' );
|
|
||||||
|
|
||||||
wp_register_style(
|
|
||||||
'wc-components',
|
|
||||||
self::get_url( 'components/style', 'css' ),
|
|
||||||
array(),
|
|
||||||
$css_file_version
|
|
||||||
);
|
|
||||||
wp_style_add_data( 'wc-components', 'rtl', 'replace' );
|
|
||||||
|
|
||||||
wp_register_style(
|
|
||||||
'wc-block-templates',
|
|
||||||
self::get_url( 'block-templates/style', 'css' ),
|
|
||||||
array(),
|
|
||||||
$css_file_version
|
|
||||||
);
|
|
||||||
wp_style_add_data( 'wc-block-templates', 'rtl', 'replace' );
|
|
||||||
|
|
||||||
wp_register_style(
|
|
||||||
'wc-product-editor',
|
|
||||||
self::get_url( 'product-editor/style', 'css' ),
|
|
||||||
array(),
|
|
||||||
$css_file_version
|
|
||||||
);
|
|
||||||
wp_style_add_data( 'wc-product-editor', 'rtl', 'replace' );
|
|
||||||
|
|
||||||
wp_register_style(
|
|
||||||
'wc-customer-effort-score',
|
|
||||||
self::get_url( 'customer-effort-score/style', 'css' ),
|
|
||||||
array(),
|
|
||||||
$css_file_version
|
|
||||||
);
|
|
||||||
wp_style_add_data( 'wc-customer-effort-score', 'rtl', 'replace' );
|
|
||||||
|
|
||||||
wp_register_style(
|
|
||||||
'wc-experimental',
|
|
||||||
self::get_url( 'experimental/style', 'css' ),
|
|
||||||
array(),
|
|
||||||
$css_file_version
|
|
||||||
);
|
|
||||||
wp_style_add_data( 'wc-experimental', 'rtl', 'replace' );
|
|
||||||
|
|
||||||
wp_localize_script(
|
|
||||||
WC_ADMIN_APP,
|
|
||||||
'wcAdminAssets',
|
|
||||||
array(
|
array(
|
||||||
'path' => plugins_url( self::get_path( 'js' ), WC_ADMIN_PLUGIN_FILE ),
|
'handle' => 'wc-admin-layout',
|
||||||
'version' => $js_file_version,
|
),
|
||||||
)
|
array(
|
||||||
|
'handle' => 'wc-components',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'handle' => 'wc-block-templates',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'handle' => 'wc-product-editor',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'handle' => 'wc-customer-effort-score',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'handle' => 'wc-experimental',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'handle' => WC_ADMIN_APP,
|
||||||
|
'dependencies' => array( 'wc-components', 'wc-admin-layout', 'wc-customer-effort-score', 'wc-product-editor', 'wp-components', 'wc-experimental' ),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'handle' => 'wc-onboarding',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
wp_register_style(
|
$css_file_version = self::get_file_version( 'css' );
|
||||||
WC_ADMIN_APP,
|
foreach ( $styles as $style ) {
|
||||||
self::get_url( 'app/style', 'css' ),
|
$handle = $style['handle'];
|
||||||
array( 'wc-components', 'wc-admin-layout', 'wc-customer-effort-score', 'wc-product-editor', 'wp-components', 'wc-experimental' ),
|
$style_path_name = isset( $scripts_map[ $handle ] ) ? $scripts_map[ $handle ] : str_replace( 'wc-', '', $handle );
|
||||||
$css_file_version
|
|
||||||
);
|
|
||||||
wp_style_add_data( WC_ADMIN_APP, 'rtl', 'replace' );
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
$style_assets_filename = self::get_script_asset_filename( $style_path_name, 'style' );
|
||||||
|
$style_assets = require WC_ADMIN_ABSPATH . WC_ADMIN_DIST_JS_FOLDER . $style_path_name . '/' . $style_assets_filename;
|
||||||
|
$version = $style_assets['version'];
|
||||||
|
} catch ( \Throwable $e ) {
|
||||||
|
// Use the default version if the asset file could not be loaded.
|
||||||
|
$version = $css_file_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dependencies = isset( $style['dependencies'] ) ? $style['dependencies'] : array();
|
||||||
wp_register_style(
|
wp_register_style(
|
||||||
'wc-onboarding',
|
$handle,
|
||||||
self::get_url( 'onboarding/style', 'css' ),
|
self::get_url( $style_path_name . '/style', 'css' ),
|
||||||
array(),
|
$dependencies,
|
||||||
$css_file_version
|
self::get_file_version( 'css', $version ),
|
||||||
);
|
);
|
||||||
wp_style_add_data( 'wc-onboarding', 'rtl', 'replace' );
|
wp_style_add_data( $handle, 'rtl', 'replace' );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -475,11 +472,32 @@ class WCAdminAssets {
|
||||||
'wc-admin-' . $script_name,
|
'wc-admin-' . $script_name,
|
||||||
self::get_url( $script_path_name . '/' . $script_name, 'js' ),
|
self::get_url( $script_path_name . '/' . $script_name, 'js' ),
|
||||||
array_merge( array( WC_ADMIN_APP ), $script_assets ['dependencies'], $dependencies ),
|
array_merge( array( WC_ADMIN_APP ), $script_assets ['dependencies'], $dependencies ),
|
||||||
self::get_file_version( 'js' ),
|
self::get_file_version( 'js', $script_assets['version'] ),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
if ( $need_translation ) {
|
if ( $need_translation ) {
|
||||||
wp_set_script_translations( 'wc-admin-' . $script_name, 'woocommerce' );
|
wp_set_script_translations( 'wc-admin-' . $script_name, 'woocommerce' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a style
|
||||||
|
*
|
||||||
|
* @param string $style_path_name The style path name.
|
||||||
|
* @param string $style_name Filename of the style to load.
|
||||||
|
* @param array $dependencies Array of any extra dependencies.
|
||||||
|
*/
|
||||||
|
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_CSS_FOLDER . $style_path_name . '/' . $style_assets_filename;
|
||||||
|
|
||||||
|
$handle = 'wc-admin-' . $style_name;
|
||||||
|
wp_enqueue_style(
|
||||||
|
$handle,
|
||||||
|
self::get_url( $style_path_name . '/' . $style_name, 'css' ),
|
||||||
|
$dependencies,
|
||||||
|
self::get_file_version( 'css', $style_assets['version'] ),
|
||||||
|
);
|
||||||
|
wp_style_add_data( $handle, 'rtl', 'replace' );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,17 +31,7 @@ class Init extends RemoteSpecsEngine {
|
||||||
add_filter( 'woocommerce_payment_gateways', array( __CLASS__, 'possibly_register_pre_install_wc_pay_promotion_gateway' ) );
|
add_filter( 'woocommerce_payment_gateways', array( __CLASS__, 'possibly_register_pre_install_wc_pay_promotion_gateway' ) );
|
||||||
add_filter( 'option_woocommerce_gateway_order', array( __CLASS__, 'set_gateway_top_of_list' ) );
|
add_filter( 'option_woocommerce_gateway_order', array( __CLASS__, 'set_gateway_top_of_list' ) );
|
||||||
add_filter( 'default_option_woocommerce_gateway_order', array( __CLASS__, 'set_gateway_top_of_list' ) );
|
add_filter( 'default_option_woocommerce_gateway_order', array( __CLASS__, 'set_gateway_top_of_list' ) );
|
||||||
|
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'load_payment_method_promotions' ) );
|
||||||
$rtl = is_rtl() ? '.rtl' : '';
|
|
||||||
|
|
||||||
wp_enqueue_style(
|
|
||||||
'wc-admin-payment-method-promotions',
|
|
||||||
WCAdminAssets::get_url( "payment-method-promotions/style{$rtl}", 'css' ),
|
|
||||||
array( 'wp-components' ),
|
|
||||||
WCAdminAssets::get_file_version( 'css' )
|
|
||||||
);
|
|
||||||
|
|
||||||
WCAdminAssets::register_script( 'wp-admin-scripts', 'payment-method-promotions', true );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -161,5 +151,13 @@ class Init extends RemoteSpecsEngine {
|
||||||
}
|
}
|
||||||
return WCPayPromotionDataSourcePoller::get_instance()->get_specs_from_data_sources();
|
return WCPayPromotionDataSourcePoller::get_instance()->get_specs_from_data_sources();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the payment method promotions scripts and styles.
|
||||||
|
*/
|
||||||
|
public static function load_payment_method_promotions() {
|
||||||
|
WCAdminAssets::register_style( 'payment-method-promotions', 'style', array( 'wp-components' ) );
|
||||||
|
WCAdminAssets::register_script( 'wp-admin-scripts', 'payment-method-promotions', true );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2163,6 +2163,9 @@ importers:
|
||||||
css-loader:
|
css-loader:
|
||||||
specifier: ^3.6.0
|
specifier: ^3.6.0
|
||||||
version: 3.6.0(webpack@5.89.0)
|
version: 3.6.0(webpack@5.89.0)
|
||||||
|
json2php:
|
||||||
|
specifier: ^0.0.7
|
||||||
|
version: 0.0.7
|
||||||
mini-css-extract-plugin:
|
mini-css-extract-plugin:
|
||||||
specifier: ^2.7.6
|
specifier: ^2.7.6
|
||||||
version: 2.7.6(webpack@5.89.0)
|
version: 2.7.6(webpack@5.89.0)
|
||||||
|
@ -39280,7 +39283,6 @@ packages:
|
||||||
|
|
||||||
/json2php@0.0.7:
|
/json2php@0.0.7:
|
||||||
resolution: {integrity: sha512-dnSoUiLAoVaMXxFsVi4CrPVYMKOuDBXTghXSmMINX44RZ8WM9cXlY7UqrQnlAcODCVO7FV3+8t/5nDKAjimLfg==}
|
resolution: {integrity: sha512-dnSoUiLAoVaMXxFsVi4CrPVYMKOuDBXTghXSmMINX44RZ8WM9cXlY7UqrQnlAcODCVO7FV3+8t/5nDKAjimLfg==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/json5@1.0.2:
|
/json5@1.0.2:
|
||||||
resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
|
resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
|
||||||
|
|
|
@ -116,7 +116,7 @@ export const scanForChanges = async (
|
||||||
base: string,
|
base: string,
|
||||||
outputStyle: 'cli' | 'github',
|
outputStyle: 'cli' | 'github',
|
||||||
clonedPath?: string,
|
clonedPath?: string,
|
||||||
exclude?: string[]
|
exclude: string[] = []
|
||||||
) => {
|
) => {
|
||||||
Logger.startTask( `Making temporary clone of ${ source }...` );
|
Logger.startTask( `Making temporary clone of ${ source }...` );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue