Skip to content

Commit

Permalink
Build: Prepare build for more script modules (WordPress#65064)
Browse files Browse the repository at this point in the history
- Rename the "interactivity" webpack build to "script modules".
- Output script-modules builds to `build-module` folder (adjacent to the `build` folder currently used for scripts).
- Add `wpScriptModulesExports` package.json field to packages with script modules and use it for script module builds. This follows the same basic syntax as [package.json `exports` fields](https://nodejs.org/api/packages.html#exports). Multiple module entrypoints can be exposed per package. However, it remains a custom field, so it is clear that these entrypoints are not intended for general consumption. In the future, module-only packages (interactivity, interactivity-router) can switch to using exports directly and likely add `type: module`.
- There are some difficulties with webpack recognizing `wpScriptModulesExports` directly, so packages are inspected programmatically in order to generate webpack script modules entrypoints.
- Adjust script module registration accordingly to find the generated script modules.

---

Co-authored-by: sirreal <[email protected]>
Co-authored-by: gziolo <[email protected]>
Co-authored-by: t-hamano <[email protected]>
  • Loading branch information
4 people authored Sep 11, 2024
1 parent b276647 commit f8a19eb
Show file tree
Hide file tree
Showing 16 changed files with 158 additions and 84 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/bundle-size.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ jobs:
- uses: preactjs/compressed-size-action@f780fd104362cfce9e118f9198df2ee37d12946c # v2.6.0
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
pattern: '{build/**/*.min.js,build/**/*.css}'
pattern: '{build/**/*.min.js,build/**/*.css,build-module/**/*.min.js}'
clean-script: 'distclean'
1 change: 1 addition & 0 deletions bin/build-plugin-zip.sh
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ zip -r gutenberg.zip \
packages/block-serialization-default-parser/*.php \
post-content.php \
$build_files \
build-module \
readme.txt \
changelog.txt \
README.md
Expand Down
4 changes: 2 additions & 2 deletions lib/interactivity-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ function gutenberg_reregister_interactivity_script_modules() {

wp_register_script_module(
'@wordpress/interactivity',
gutenberg_url( '/build/interactivity/' . ( SCRIPT_DEBUG ? 'debug.min.js' : 'index.min.js' ) ),
gutenberg_url( '/build-module/' . ( SCRIPT_DEBUG ? 'interactivity/debug.min.js' : 'interactivity/index.min.js' ) ),
array(),
$default_version
);

wp_register_script_module(
'@wordpress/interactivity-router',
gutenberg_url( '/build/interactivity/router.min.js' ),
gutenberg_url( '/build-module/interactivity-router/index.min.js' ),
array( '@wordpress/interactivity' ),
$default_version
);
Expand Down
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@wordpress/i18n": "file:packages/i18n",
"@wordpress/icons": "file:packages/icons",
"@wordpress/interactivity": "file:packages/interactivity",
"@wordpress/interactivity-router": "file:packages/interactivity-router",
"@wordpress/interface": "file:packages/interface",
"@wordpress/is-shallow-equal": "file:packages/is-shallow-equal",
"@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts",
Expand Down
7 changes: 7 additions & 0 deletions packages/block-library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
"src/**/*.scss",
"{src,build,build-module}/*/init.js"
],
"wpScriptModuleExports": {
"./file/view": "./build-module/file/view.js",
"./image/view": "./build-module/image/view.js",
"./navigation/view": "./build-module/navigation/view.js",
"./query/view": "./build-module/query/view.js",
"./search/view": "./build-module/search/view.js"
},
"dependencies": {
"@babel/runtime": "^7.16.0",
"@wordpress/a11y": "file:../a11y",
Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/file/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function render_block_core_file( $attributes, $content ) {
if ( ! empty( $attributes['displayPreview'] ) ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build/interactivity/file.min.js' );
$module_url = gutenberg_url( '/build-module/block-library/file/view.min.js' );
}

wp_register_script_module(
Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/image/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function render_block_core_image( $attributes, $content, $block ) {
) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build/interactivity/image.min.js' );
$module_url = gutenberg_url( '/build-module/block-library/image/view.min.js' );
}

wp_register_script_module(
Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/navigation/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ private static function handle_view_script_module_loading( $attributes, $block,
if ( static::is_interactive( $attributes, $inner_blocks ) ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build/interactivity/navigation.min.js' );
$module_url = gutenberg_url( '/build-module/block-library/navigation/view.min.js' );
}

wp_register_script_module(
Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/query/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function render_block_core_query( $attributes, $content, $block ) {
if ( $is_interactive ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build/interactivity/query.min.js' );
$module_url = gutenberg_url( '/build-module/block-library/query/view.min.js' );
}

wp_register_script_module(
Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/search/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ function render_block_core_search( $attributes ) {
if ( $is_expandable_searchfield ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build/interactivity/search.min.js' );
$module_url = gutenberg_url( '/build-module/block-library/search/view.min.js' );
}

wp_register_script_module(
Expand Down
1 change: 1 addition & 0 deletions packages/interactivity-router/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"module": "build-module/index.js",
"react-native": "src/index",
"types": "build-types",
"wpScriptModuleExports": "./build-module/index.js",
"dependencies": {
"@wordpress/interactivity": "file:../interactivity"
},
Expand Down
4 changes: 4 additions & 0 deletions packages/interactivity/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
"module": "build-module/index.js",
"react-native": "src/index",
"types": "build-types",
"wpScriptModuleExports": {
".": "./build-module/index.js",
"./debug": "./build-module/debug.js"
},
"dependencies": {
"@preact/signals": "^1.2.2",
"preact": "^10.19.3"
Expand Down
74 changes: 0 additions & 74 deletions tools/webpack/interactivity.js

This file was deleted.

133 changes: 133 additions & 0 deletions tools/webpack/script-modules.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/**
* External dependencies
*/
const { join } = require( 'path' );

/**
* WordPress dependencies
*/
const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' );

/**
* Internal dependencies
*/
const { baseConfig, plugins } = require( './shared' );

const WORDPRESS_NAMESPACE = '@wordpress/';
const { createRequire } = require( 'node:module' );

const rootURL = new URL( '..', `file://${ __dirname }` );
const fromRootRequire = createRequire( rootURL );

/** @type {Iterable<[string, string]>} */
const iterableDeps = Object.entries(
fromRootRequire( './package.json' ).dependencies
);

/** @type {Map<string, string>} */
const gutenbergScriptModules = new Map();
for ( const [ packageName, versionSpecifier ] of iterableDeps ) {
if (
! packageName.startsWith( WORDPRESS_NAMESPACE ) ||
! versionSpecifier.startsWith( 'file:' ) ||
packageName.startsWith( WORDPRESS_NAMESPACE + 'react-native' )
) {
continue;
}

const packageRequire = createRequire(
// Remove the leading "file:" specifier to build a package URL.
new URL( `${ versionSpecifier.substring( 5 ) }/`, rootURL )
);

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( /^\.\/?/, '' );

gutenbergScriptModules.set(
`${ moduleName }/${ name }`,
packageRequire.resolve( exportPath )
);
}
}

module.exports = {
...baseConfig,
name: 'script-modules',
entry: Object.fromEntries( gutenbergScriptModules.entries() ),
experiments: {
outputModule: true,
},
output: {
devtoolNamespace: 'wp',
filename: './build-module/[name].min.js',
library: {
type: 'module',
},
path: join( __dirname, '..', '..' ),
environment: { module: true },
module: true,
chunkFormat: 'module',
asyncChunks: false,
},
resolve: {
extensions: [ '.js', '.ts', '.tsx' ],
},
module: {
rules: [
{
test: /\.(j|t)sx?$/,
exclude: /node_modules/,
use: [
{
loader: require.resolve( 'babel-loader' ),
options: {
cacheDirectory:
process.env.BABEL_CACHE_DIRECTORY || true,
babelrc: false,
configFile: false,
presets: [
'@babel/preset-typescript',
'@babel/preset-react',
],
},
},
],
},
],
},
plugins: [ ...plugins, new DependencyExtractionWebpackPlugin() ],
watchOptions: {
ignored: [ '**/node_modules' ],
aggregateTimeout: 500,
},
};
4 changes: 2 additions & 2 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
*/
const blocksConfig = require( './tools/webpack/blocks' );
const developmentConfigs = require( './tools/webpack/development' );
const interactivity = require( './tools/webpack/interactivity' );
const scriptModules = require( './tools/webpack/script-modules' );
const packagesConfig = require( './tools/webpack/packages' );
const vendorsConfig = require( './tools/webpack/vendors' );

module.exports = [
...blocksConfig,
interactivity,
scriptModules,
packagesConfig,
...developmentConfigs,
...vendorsConfig,
Expand Down

0 comments on commit f8a19eb

Please sign in to comment.