JavaScript: Add new Modules API.
This changeset adds a new API for WordPress, designed to work with native ES Modules and Import Maps. It introduces functions such as wp_register_module
, and wp_enqueue_module
.
The API aims to provide a familiar experience to the existing WP_Scripts
class, offering similar functionality. However, it's not intended to duplicate the exact functionality of WP_Scripts
; rather, it is carefully tailored to address the specific needs and capabilities of ES modules.
For this initial version, the current proposal is intentionally simplistic, covering only the essential features needed to work with ES modules. Other enhancements and optimizations can be added later as the community identifies additional requirements and use cases.
Differences Between WP_Script_Modules and WP_Scripts
Dependency Specification
With WP_Script_Modules
, the array of dependencies supports not only strings but also arrays that include the dependency import type (static
or dynamic
). This design choice allows for future extensions of dependency properties, such as adding a version
property to support "scopes" within import maps.
Module Identifier
Instead of a handle, WP_Script_Modules
utilizes the module identifier, aligning with the module identifiers used in JavaScript files and import maps.
Deregistration
There is no equivalent of wp_deregister_script
at this stage.
API
wp_register_module( $module_identifier, $src, $deps, $version )
Registers a module.
// Registers a module with dependencies and versioning.
wp_register_module(
'my-module',
'/path/to/my-module.js',
array( 'static-dependency-1', 'static-dependency-2' ),
'1.2.3'
);
// my-module.js
import { ... } from 'static-dependency-1';
import { ... } from 'static-dependency-2';
// ...
// Registers a module with a dynamic dependency.
wp_register_module(
'my-module',
'/path/to/my-module.js',
array(
'static-dependency',
array(
'id' => 'dynamic-dependency',
'import' => 'dynamic'
),
)
);
// my-module.js
import { ... } from 'static-dependency';
// ...
const dynamicModule = await import('dynamic-dependency');
wp_enqueue_module( $module_identifier, $src, $deps, $version )
Enqueues a module. If a source is provided, it will also register the module.
wp_enqueue_module( 'my-module' );
wp_dequeue_module( $module_identifier )
Dequeues a module.
wp_dequeue_module( 'my-module' );
Output
- When modules are enqueued, they are printed within script tags containing
type="module"
attributes.
- Additionally, static dependencies of enqueued modules utilize
link
tags with rel="modulepreload"
attributes.
- Lastly, an import map is generated and inserted using a
<script type="importmap">
tag.
<script type="module" src="/path/to/my-module.js" id="my-module"></script>
<link rel="modulepreload" href="/path/to/static-dependency.js" id="static-dependency" />
<script type="importmap">
{
"imports": {
"static-dependency": "/path/to/static-dependency.js",
"dynamic-dependency": "/path/to/dynamic-dependency.js"
}
}
</script>
Import Map Polyfill Requirement
Even though all major browsers already support import maps, an import map polyfill is required until the percentage of users using old browser versions without import map support drops significantly.
This work is ongoing and will be added once it's ready. Progress is tracked in #60232.
Props luisherranz, idad5, costdev, neffff, joemcgill, jorbin, swissspidy, jonsurrell, flixos90, gziolo, westonruter.
Fixes #56313.