-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Script Modules API #5818
Script Modules API #5818
Conversation
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
I see that PHP 8.3 has some deprecations when using EDIT: I switched to EDIT 2: Fixed now in f13a068! |
Thanks for the review, @swissspidy. I've made all the necessary changes 🙂 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used this PR to build out what it would take to handle viewModule
in block.json
(analagous module version of viewScript
).
One thing that I encountered is that module registration returns null
. We don't have a return value that indicates success or failure. Look at this block:
wordpress-develop/src/wp-includes/blocks.php
Lines 190 to 199 in 455044e
$result = wp_register_script( | |
$script_handle, | |
$script_uri, | |
$script_dependencies, | |
isset( $script_asset['version'] ) ? $script_asset['version'] : false, | |
$script_args | |
); | |
if ( ! $result ) { | |
return false; | |
} |
When implementing similar handling for modules, there's no return value from wp_register_module
or WP_Modules::register
, so we end up optimistically continuing as if the module is correctly registered.
Was that an intentional design decision? I'd expect to have some return value, maybe the module ID or an array that's descriptive of the module ([ id => …, src => …, …]
) or false
in case of failure.
When I was studying WP Scripts, I saw that if ( isset( $this->registered[ $handle ] ) ) {
return false;
}
$this->registered[ $handle ] = new _WP_Dependency( $handle, $src, $deps, $ver, $args );
// ...
return true; So, it works like this:
In both cases, the script is successfully registered.
That's my point. It doesn't matter what WP Scripts returns, the script is always registered so we should be able to continue as if the script is correctly registered. I'm not opposed to mimicking the So, is there a use case where that |
Good point. I agree, it doesn't seem very helpful to distinguish between "registered on this call" and "already registered" if the result is the same. If there's no real failure scenario, it seems fine to always return |
Ok. Thanks, Jon. Let's keep it as it is for now then, just to keep open the possibility of returning something useful in the future or until we discover of use case for the WP Scripts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@luisherranz The logic here looks great to me.
I do however think the implementation should rely on a non-static class, as only stateless classes/methods should be static. The existing WP_Scripts
and WP_Styles
classes aren't static either, so that's another (albeit minor) reason.
In the case of It's going to be challenging to replicate the same code with the currently proposed approach when the only possibility is to dequeue the module. In the shared example, all these scripts might not be enqueued as it happens later in the process. However, maybe it's fine, as when using the proposed implementation for modules, the plugin can register the same handles again, and they will get successfuly overridden. The only difference would be that some unused modules would remain registered and hopefully never enqueued.
|
@felixarntz: thanks! It makes sense. I'll make those changes 🙂 @gziolo: So the use case for |
Yes, this is how it works. There is a check that ensures that only registered scripts get printed to make it possible to safely deregister a script. |
@luisherranz Interesting. I wasn't aware of JSON and CSS also being on the roadmap for being modules. Nevertheless, I think
Additionally, all of these modules alike end up getting printed in an importmap |
322cc83
to
adb5913
Compare
Ok! Thanks, Weston. I've renamed the class to I've also added support to register the script with a single call to the enqueue function, as requested by @aaronjorbin in the ticket. I still agree that it would have made sense to separate both registration and enqueuing as a way to teach people that those are two separate steps (especially when working with modules where registered modules can't only end up being enqueued, but also preloaded or added to the import map), but as @aaronjorbin pointed out, the wp_enqueue_style( 'my-style', '/styles.css' );
wp_register_module( 'my-module', '/module.js' );
wp_enqueue_module( 'my-module' ); So now, this also works: wp_enqueue_style( 'my-style', '/styles.css' );
wp_enqueue_module( 'my-module', '/module.js' ); From my point of view, I think this is in a great state. I don't have plans to add any other changes to this initial version. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Now that the |
I'd keep it as |
Works for me! And if we end up deciding otherwise, we can always change it in a follow-up 😊 |
Committed to Core in https://core.trac.wordpress.org/changeset/57269. Thank you, folks! This is big 🎉 |
Follow-up tickets:
|
It's great to see this committed! 🎉 Nevertheless, I think the naming topic was wrapped a bit quickly as it was only initiated 2 days ago by @westonruter, so that didn't leave much room for other people's thoughts before the commit. We can of course follow up if needed, but a final decision on naming needs to happen soon before more other things are implemented on top of the API. I think we should continue the discussion, either here or in a new issue. I personally find it a confusing choice to go with
I don't have a strong opinion which way to go, but I think the current solution is neither. |
IMO, I think the functions should be |
It makes perfect sense after the class name changes were applied. |
Another +1 for this. |
Seems unanimous, then. I'll prepare a PR with the renaming. |
Trac ticket: https://core.trac.wordpress.org/ticket/56313
EDIT: I've updated the description to showcase the latest changes.
This PR proposes a new Modules API for WordPress, designed to work with native ES Modules and Import Maps. It introduces functions such as
wp_register_script_module
, andwp_enqueue_script_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 ofWP_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 just strings but also arrays that include the dependency import type (static
ordynamic
). This design choice allows for future extensions of dependency properties, such as adding aversion
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_module
at this stage.API
wp_register_script_module( $module_identifier, $src, $deps, $version )
Registers a module.
wp_enqueue_script_module( $module_identifier, $src, $deps, $version )
Enqueues a module. If it includes a src, it will also register the module.
wp_dequeue_script_module( $module_identifier )
Dequeues a module.
Output
type="module"
attributes.link
tags withrel="modulepreload"
attributes.<script type="importmap">
tag.Import Map Polyfill Requirement
Even though all the 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 to this PR once it's ready. Contributors can follow the progress in the associated GitHub issue: guybedford/es-module-shims#406.
Feedback
This Modules API proposal is open for feedback and further discussion. Please contribute ideas, potential use cases, or any other thoughts that could make this feature robust and broadly useful for the WordPress community. Please use the Trac Ticket or this pull request.