wordpress/tools/webpack/script-modules.js
Greg Ziółkowski 0b8b80449f 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
2024-09-24 07:33:55 +00:00

120 lines
2.9 KiB
JavaScript

/**
* 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;
};