mirror of
git://develop.git.wordpress.org/
synced 2025-01-16 12:29:54 +01:00
Build: Prepare for more Script Modules
This is a companion to https://github.com/WordPress/gutenberg/pull/65460 that requires syncing in WordPress Core. Namely, the block-library changes require registration with their updated script module IDs so that the blocks continue to work correctly. They key improvement is script modules registration is handled in one central place, and a combined asset file is used to improve the performance by avoiding multiple disk operations for every individual file. Props jonsurrell, gziolo, wildworks, noisysocks. See #60647, #59462. git-svn-id: https://develop.svn.wordpress.org/trunk@59083 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
a39079946a
commit
0b8b80449f
1
.gitignore
vendored
1
.gitignore
vendored
@ -31,6 +31,7 @@ wp-tests-config.php
|
||||
/src/wp-admin/js
|
||||
/src/wp-includes/assets/*
|
||||
!/src/wp-includes/assets/script-loader-packages.min.php
|
||||
!/src/wp-includes/assets/script-modules-packages.min.php
|
||||
/src/wp-includes/js
|
||||
/src/wp-includes/css/dist
|
||||
/src/wp-includes/css/*.min.css
|
||||
|
@ -56,6 +56,7 @@ module.exports = function(grunt) {
|
||||
'wp-includes/css/dist',
|
||||
'wp-includes/blocks/**/*.css',
|
||||
'!wp-includes/assets/script-loader-packages.min.php',
|
||||
'!wp-includes/assets/script-modules-packages.min.php',
|
||||
],
|
||||
|
||||
// Prepend `dir` to `file`, and keep `!` in place.
|
||||
|
1
src/wp-includes/assets/script-modules-packages.min.php
Normal file
1
src/wp-includes/assets/script-modules-packages.min.php
Normal file
@ -0,0 +1 @@
|
||||
<?php return array('interactivity/index.min.js' => array('dependencies' => array(), 'version' => '2d6d1fdbcb3fda39c768', 'type' => 'module'), 'interactivity/debug.min.js' => array('dependencies' => array(), 'version' => '1ccc67b05c275e51a8f8', 'type' => 'module'), 'interactivity-router/index.min.js' => array('dependencies' => array('@wordpress/interactivity'), 'version' => '64645ef3cd2d32860d7d', 'type' => 'module'), 'block-library/file/view.min.js' => array('dependencies' => array('@wordpress/interactivity'), 'version' => 'fdc2f6842e015af83140', 'type' => 'module'), 'block-library/image/view.min.js' => array('dependencies' => array('@wordpress/interactivity'), 'version' => 'acfec7b3c0be4a859b31', 'type' => 'module'), 'block-library/navigation/view.min.js' => array('dependencies' => array('@wordpress/interactivity'), 'version' => '8ff192874fc8910a284c', 'type' => 'module'), 'block-library/query/view.min.js' => array('dependencies' => array('@wordpress/interactivity', array('id' => '@wordpress/interactivity-router', 'import' => 'dynamic')), 'version' => 'f4c91c89fa5271f3dad9', 'type' => 'module'), 'block-library/search/view.min.js' => array('dependencies' => array('@wordpress/interactivity'), 'version' => '2a73400a693958f604de', 'type' => 'module'));
|
@ -570,6 +570,7 @@ add_action( 'set_current_user', 'kses_init' );
|
||||
// Script Loader.
|
||||
add_action( 'wp_default_scripts', 'wp_default_scripts' );
|
||||
add_action( 'wp_default_scripts', 'wp_default_packages' );
|
||||
add_action( 'wp_default_scripts', 'wp_default_script_modules' );
|
||||
|
||||
add_action( 'wp_enqueue_scripts', 'wp_localize_jquery_ui_datepicker', 1000 );
|
||||
add_action( 'wp_enqueue_scripts', 'wp_common_block_scripts_and_styles' );
|
||||
|
@ -281,33 +281,20 @@ final class WP_Interactivity_API {
|
||||
/**
|
||||
* Registers the `@wordpress/interactivity` script modules.
|
||||
*
|
||||
* @deprecated 6.7.0 Script Modules registration is handled by {@see wp_default_script_modules()}.
|
||||
*
|
||||
* @since 6.5.0
|
||||
*/
|
||||
public function register_script_modules() {
|
||||
$suffix = wp_scripts_get_suffix();
|
||||
|
||||
wp_register_script_module(
|
||||
'@wordpress/interactivity',
|
||||
includes_url( "js/dist/interactivity$suffix.js" )
|
||||
);
|
||||
|
||||
wp_register_script_module(
|
||||
'@wordpress/interactivity-router',
|
||||
includes_url( "js/dist/interactivity-router$suffix.js" ),
|
||||
array( '@wordpress/interactivity' )
|
||||
);
|
||||
_deprecated_function( __METHOD__, '6.7.0', 'wp_default_script_modules' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the necessary hooks for the Interactivity API.
|
||||
*
|
||||
* @since 6.5.0
|
||||
* @since 6.7.0 Use the {@see "script_module_data_{$module_id}"} filter to pass client-side data.
|
||||
*/
|
||||
public function add_hooks() {
|
||||
add_action( 'wp_enqueue_scripts', array( $this, 'register_script_modules' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'register_script_modules' ) );
|
||||
|
||||
add_filter( 'script_module_data_@wordpress/interactivity', array( $this, 'filter_script_module_interactivity_data' ) );
|
||||
}
|
||||
|
||||
|
@ -123,3 +123,53 @@ function wp_dequeue_script_module( string $id ) {
|
||||
function wp_deregister_script_module( string $id ) {
|
||||
wp_script_modules()->deregister( $id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all the default WordPress Script Modules.
|
||||
*
|
||||
* @since 6.7.0
|
||||
*/
|
||||
function wp_default_script_modules() {
|
||||
$suffix = defined( 'WP_RUN_CORE_TESTS' ) ? '.min' : wp_scripts_get_suffix();
|
||||
|
||||
/*
|
||||
* Expects multidimensional array like:
|
||||
*
|
||||
* 'interactivity/index.min.js' => array('dependencies' => array(…), 'version' => '…'),
|
||||
* 'interactivity/debug.min.js' => array('dependencies' => array(…), 'version' => '…'),
|
||||
* 'interactivity-router/index.min.js' => …
|
||||
*/
|
||||
$assets = include ABSPATH . WPINC . "/assets/script-modules-packages{$suffix}.php";
|
||||
|
||||
foreach ( $assets as $file_name => $script_module_data ) {
|
||||
/*
|
||||
* Build the WordPress Script Module ID from the file name.
|
||||
* Prepend `@wordpress/` and remove extensions and `/index` if present:
|
||||
* - interactivity/index.min.js => @wordpress/interactivity
|
||||
* - interactivity/debug.min.js => @wordpress/interactivity/debug
|
||||
* - block-library/query/view.js => @wordpress/block-library/query/view
|
||||
*/
|
||||
$script_module_id = '@wordpress/' . preg_replace( '~(?:/index)?(?:\.min)?\.js$~D', '', $file_name, 1 );
|
||||
|
||||
switch ( $script_module_id ) {
|
||||
/*
|
||||
* Interactivity exposes two entrypoints, "/index" and "/debug".
|
||||
* "/debug" should replalce "/index" in devlopment.
|
||||
*/
|
||||
case '@wordpress/interactivity/debug':
|
||||
if ( ! SCRIPT_DEBUG ) {
|
||||
continue 2;
|
||||
}
|
||||
$script_module_id = '@wordpress/interactivity';
|
||||
break;
|
||||
case '@wordpress/interactivity':
|
||||
if ( SCRIPT_DEBUG ) {
|
||||
continue 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$path = "/wp-includes/js/dist/script-modules/{$file_name}";
|
||||
wp_register_script_module( $script_module_id, $path, $script_module_data['dependencies'], $script_module_data['version'] );
|
||||
}
|
||||
}
|
||||
|
@ -211,6 +211,17 @@ class Tests_Interactivity_API_WpInteractivityAPI extends WP_UnitTestCase {
|
||||
$this->expectOutputString( '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the deprecated register_script_modules method is deprecated but does not throw.
|
||||
*
|
||||
* @ticket 60647
|
||||
*
|
||||
* @expectedDeprecated WP_Interactivity_API::register_script_modules
|
||||
*/
|
||||
public function test_register_script_modules_deprecated() {
|
||||
$this->interactivity->register_script_modules();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up an activity, runs an optional callback, and returns a MockAction for inspection.
|
||||
*
|
||||
@ -221,7 +232,6 @@ class Tests_Interactivity_API_WpInteractivityAPI extends WP_UnitTestCase {
|
||||
*/
|
||||
private function get_script_data_filter_result( ?Closure $callback = null ): MockAction {
|
||||
$this->interactivity->add_hooks();
|
||||
$this->interactivity->register_script_modules();
|
||||
wp_enqueue_script_module( '@wordpress/interactivity' );
|
||||
$filter = new MockAction();
|
||||
add_filter( 'script_module_data_@wordpress/interactivity', array( $filter, 'filter' ) );
|
||||
|
@ -1,76 +0,0 @@
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const DependencyExtractionPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' );
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
baseDir,
|
||||
getBaseConfig,
|
||||
normalizeJoin,
|
||||
MODULES,
|
||||
WORDPRESS_NAMESPACE,
|
||||
} = require( './shared' );
|
||||
|
||||
module.exports = function (
|
||||
env = { environment: 'production', watch: false, buildTarget: false }
|
||||
) {
|
||||
const mode = env.environment;
|
||||
const suffix = mode === 'production' ? '.min' : '';
|
||||
let buildTarget = env.buildTarget
|
||||
? env.buildTarget
|
||||
: mode === 'production'
|
||||
? 'build'
|
||||
: 'src';
|
||||
buildTarget = buildTarget + '/wp-includes';
|
||||
|
||||
const baseConfig = getBaseConfig( env );
|
||||
const config = {
|
||||
...baseConfig,
|
||||
entry: MODULES.map( ( packageName ) =>
|
||||
packageName.replace( WORDPRESS_NAMESPACE, '' )
|
||||
).reduce( ( memo, packageName ) => {
|
||||
const path =
|
||||
'development' === mode && 'interactivity' === packageName
|
||||
? 'interactivity/build-module/debug'
|
||||
: packageName;
|
||||
memo[ packageName ] = {
|
||||
import: normalizeJoin(
|
||||
baseDir,
|
||||
`node_modules/@wordpress/${ path }`
|
||||
),
|
||||
};
|
||||
|
||||
return memo;
|
||||
}, {} ),
|
||||
experiments: {
|
||||
outputModule: true,
|
||||
},
|
||||
output: {
|
||||
devtoolNamespace: 'wp',
|
||||
filename: `[name]${ suffix }.js`,
|
||||
path: normalizeJoin( baseDir, `${ buildTarget }/js/dist` ),
|
||||
library: {
|
||||
type: 'module',
|
||||
},
|
||||
environment: { module: true },
|
||||
},
|
||||
externalsType: 'module',
|
||||
externals: {
|
||||
'@wordpress/interactivity': '@wordpress/interactivity',
|
||||
'@wordpress/interactivity-router':
|
||||
'import @wordpress/interactivity-router',
|
||||
},
|
||||
plugins: [
|
||||
...baseConfig.plugins,
|
||||
new DependencyExtractionPlugin( {
|
||||
injectPolyfill: false,
|
||||
useDefaults: false,
|
||||
} ),
|
||||
],
|
||||
};
|
||||
|
||||
return config;
|
||||
};
|
119
tools/webpack/script-modules.js
Normal file
119
tools/webpack/script-modules.js
Normal file
@ -0,0 +1,119 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
const { createRequire } = require( 'node:module' );
|
||||
const { dirname } = require( 'node:path' );
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const DependencyExtractionPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' );
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
baseDir,
|
||||
getBaseConfig,
|
||||
normalizeJoin,
|
||||
MODULES,
|
||||
SCRIPT_AND_MODULE_DUAL_PACKAGES,
|
||||
WORDPRESS_NAMESPACE,
|
||||
} = require( './shared' );
|
||||
|
||||
/** @type {Map<string, string>} */
|
||||
const scriptModules = new Map();
|
||||
for ( const packageName of MODULES.concat( SCRIPT_AND_MODULE_DUAL_PACKAGES ) ) {
|
||||
const packageRequire = createRequire(
|
||||
`${ dirname( require.resolve( `${ packageName }/package.json` ) ) }/`
|
||||
);
|
||||
|
||||
const depPackageJson = packageRequire( './package.json' );
|
||||
if ( ! Object.hasOwn( depPackageJson, 'wpScriptModuleExports' ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const moduleName = packageName.substring( WORDPRESS_NAMESPACE.length );
|
||||
let { wpScriptModuleExports } = depPackageJson;
|
||||
|
||||
// Special handling for { "wpScriptModuleExports": "./build-module/index.js" }.
|
||||
if ( typeof wpScriptModuleExports === 'string' ) {
|
||||
wpScriptModuleExports = { '.': wpScriptModuleExports };
|
||||
}
|
||||
|
||||
if ( Object.getPrototypeOf( wpScriptModuleExports ) !== Object.prototype ) {
|
||||
throw new Error( 'wpScriptModuleExports must be an object' );
|
||||
}
|
||||
|
||||
for ( const [ exportName, exportPath ] of Object.entries(
|
||||
wpScriptModuleExports
|
||||
) ) {
|
||||
if ( typeof exportPath !== 'string' ) {
|
||||
throw new Error( 'wpScriptModuleExports paths must be strings' );
|
||||
}
|
||||
|
||||
if ( ! exportPath.startsWith( './' ) ) {
|
||||
throw new Error(
|
||||
'wpScriptModuleExports paths must start with "./"'
|
||||
);
|
||||
}
|
||||
|
||||
const name =
|
||||
exportName === '.' ? 'index' : exportName.replace( /^\.\/?/, '' );
|
||||
|
||||
scriptModules.set(
|
||||
`${ moduleName }/${ name }`,
|
||||
packageRequire.resolve( exportPath )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function (
|
||||
env = { environment: 'production', watch: false, buildTarget: false }
|
||||
) {
|
||||
const mode = env.environment;
|
||||
const suffix = mode === 'production' ? '.min' : '';
|
||||
let buildTarget = env.buildTarget
|
||||
? env.buildTarget
|
||||
: mode === 'production'
|
||||
? 'build'
|
||||
: 'src';
|
||||
buildTarget = buildTarget + '/wp-includes';
|
||||
|
||||
const baseConfig = getBaseConfig( env );
|
||||
const config = {
|
||||
...baseConfig,
|
||||
entry: Object.fromEntries( scriptModules.entries() ),
|
||||
experiments: {
|
||||
outputModule: true,
|
||||
},
|
||||
output: {
|
||||
devtoolNamespace: 'wp',
|
||||
filename: `[name]${ suffix }.js`,
|
||||
path: normalizeJoin(
|
||||
baseDir,
|
||||
`${ buildTarget }/js/dist/script-modules`
|
||||
),
|
||||
library: {
|
||||
type: 'module',
|
||||
},
|
||||
environment: { module: true },
|
||||
module: true,
|
||||
chunkFormat: 'module',
|
||||
asyncChunks: false,
|
||||
},
|
||||
plugins: [
|
||||
...baseConfig.plugins,
|
||||
new DependencyExtractionPlugin( {
|
||||
injectPolyfill: false,
|
||||
combineAssets: true,
|
||||
combinedOutputFile: normalizeJoin(
|
||||
baseDir,
|
||||
`${ buildTarget }/assets/script-modules-packages${ suffix }.php`
|
||||
),
|
||||
} ),
|
||||
],
|
||||
};
|
||||
|
||||
return config;
|
||||
};
|
@ -102,6 +102,9 @@ const MODULES = [
|
||||
'@wordpress/interactivity',
|
||||
'@wordpress/interactivity-router',
|
||||
];
|
||||
const SCRIPT_AND_MODULE_DUAL_PACKAGES = [
|
||||
'@wordpress/block-library',
|
||||
];
|
||||
const WORDPRESS_NAMESPACE = '@wordpress/';
|
||||
|
||||
module.exports = {
|
||||
@ -111,5 +114,6 @@ module.exports = {
|
||||
stylesTransform,
|
||||
BUNDLED_PACKAGES,
|
||||
MODULES,
|
||||
SCRIPT_AND_MODULE_DUAL_PACKAGES,
|
||||
WORDPRESS_NAMESPACE,
|
||||
};
|
||||
|
@ -2,7 +2,7 @@ const blocksConfig = require( './tools/webpack/blocks' );
|
||||
const developmentConfig = require( './tools/webpack/development' );
|
||||
const mediaConfig = require( './tools/webpack/media' );
|
||||
const packagesConfig = require( './tools/webpack/packages' );
|
||||
const modulesConfig = require( './tools/webpack/modules' );
|
||||
const scriptModulesConfig = require( './tools/webpack/script-modules' );
|
||||
const vendorsConfig = require( './tools/webpack/vendors' );
|
||||
|
||||
module.exports = function( env = { environment: "production", watch: false, buildTarget: false } ) {
|
||||
@ -19,7 +19,7 @@ module.exports = function( env = { environment: "production", watch: false, buil
|
||||
...developmentConfig( env ),
|
||||
mediaConfig( env ),
|
||||
packagesConfig( env ),
|
||||
modulesConfig( env ),
|
||||
scriptModulesConfig( env ),
|
||||
...vendorsConfig( env ),
|
||||
];
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user