-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Allow classic scripts to depend on modules #8024
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
base: trunk
Are you sure you want to change the base?
Allow classic scripts to depend on modules #8024
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. |
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
@luisherranz @youknowriad @swissspidy @gziolo I'd love to have your review on this approach to allowing classic scripts to depend on script modules. |
This allows for script modules to be exposed in the import map regardless of being a dependency or enqueued. This will enable scripts to depend on script modules by requesting they be exposed.
The + operator merges arrays with key overwriting. array_merge renumbers numeric arrays, the desired behavior in this case.
This works, but it only works as long as scripts are printed before the importmap is printed. That is undesireable sometimes. An alternate approach may be to invert this scheme and have script modules inspect enqueued and printed scripts before printing the importmap.
7a6c553 to
45cacbb
Compare
| _doing_it_wrong( | ||
| $function_name, | ||
| sprintf( | ||
| /* translators: 1: $args, 2: List of unrecognized keys. */ | ||
| __( 'Unrecognized keys in the %1$s array: %2$s.' ), | ||
| '$args', | ||
| implode( wp_get_list_item_separator(), $unknown_keys ) | ||
| ), | ||
| '7.0.0' | ||
| ); |
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.
Importantly, this will catch cases where someone “mispells” the arg module_dependencies, like moduel_dependencys. I went with the full “dependencies” in the name as opposed to module_deps because there is also WP_Dependencies. See also Naming Conventions to not abbreviate names unnecessarily.
|
Gemini review: Review of changes in The changes introduce logic to include script module dependencies defined in classic scripts (via the General Observations
ConclusionThe changes are high quality, verified by tests, and improve the codebase's maintainability while adding the requested feature. Addressing the typo in the comment is the only immediate action recommended. |
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.
Pull request overview
Enables classic (non-module) scripts to declare dependencies on registered script modules so that those modules (and their transitive dependencies) are added to the script modules import map, making them available to classic scripts via dynamic import().
Changes:
- Adds support for declaring classic-script module dependencies via
$args['module_dependencies']inwp_register_script()/wp_enqueue_script(). - Extends
WP_Script_Modulesimport map generation to include module IDs referenced by enqueued classic scripts. - Adds validation and new PHPUnit coverage for
module_dependenciesand for unrecognized$argskeys.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/wp-includes/functions.wp-scripts.php |
Introduces _wp_scripts_add_args_data() and documents/supports module_dependencies in script $args. |
src/wp-includes/class-wp-scripts.php |
Adds module_dependencies validation/sanitization in WP_Scripts::add_data(). |
src/wp-includes/class-wp-script-modules.php |
Updates import map generation to discover module dependencies from enqueued classic scripts. |
tests/phpunit/tests/script-modules/wpScriptModules.php |
Adds tests ensuring classic-script module deps are included in the import map and missing deps trigger a notice. |
tests/phpunit/tests/dependencies/scripts.php |
Adds tests for unrecognized $args keys and module_dependencies validation behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
|
Updated Gemini review (with nitpicks not needing actioning): Review of changes in The changes introduce functionality to allow classic scripts to declare dependencies on script modules, including validation, processing, and handling within the import map generation. The implementation also refactors script registration logic to reduce duplication. Observations
Nitpicks
ConclusionThe code is robust, follows WordPress coding standards, and the test coverage is thorough. The refactoring improves maintainability. Plan: |
westonruter
left a comment
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.
@sirreal I'm excited about getting this capability into core! If you approve the changes, let's get this committed. You can do the honors if you'd like!
… at 9acd7f0 Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
… at 9acd7f0 Co-authored-by: Jon Surrell <[email protected]> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
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.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| array( | ||
| 'id' => 'example2', | ||
| ), |
Copilot
AI
Feb 2, 2026
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.
This test case includes an array format array('id' => 'example2') for module dependencies, but there is no test coverage for validating that this array format is handled correctly. Consider adding a test case that specifically validates the array format with an 'id' key is properly processed.
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.
This is not factual. There is a test case for it being handled properly, but it is in scripts.php. The bottom of this same test method in fact shows that the format is handled properly, as example2 appears in the array returned by get_import_map.
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
sirreal
left a comment
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 have one final thing I'd like to consider, otherwise this seems ready to me. Thanks again for all your work on it @westonruter 🙂
…gs_data(). Automatically determine the calling function name using debug_backtrace() for context in _doing_it_wrong() calls. Co-authored-by: Jon Surrell <[email protected]> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
sirreal
left a comment
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.
✅ This is ready!
@westonruter feel free to merge if you're ready. Otherwise, I'll get it landed this week. I don't mind either way 🙂
This change allows classic scripts to declare dependencies on Script Modules.
Classic scripts can declare module dependencies by passing a
module_dependencieskey in the$argsarray ofwp_register_script()orwp_enqueue_script().In order for a classic script to have access to a script module, the script module must appear in the import map so that it can be accessed by its module identifier from the classic script in a dynamic import (e.g.
import( '@example/module' )).For a classic script to depend on a module, it must declare that dependency via the new
module_dependenciesargument. When the script modules import map is printed, it inspects all enqueued classic scripts (and their dependencies recursively) to search for these declared module dependencies and ensures those modules are included in the import map.The implementation introduces a new
_wp_scripts_add_args_data()helper function to consolidate argument validation and processing forwp_register_script()andwp_enqueue_script(), reducing code duplication. This function validates that the$argsarray only contains recognized keys (strategy,in_footer,fetchpriority,module_dependencies) and triggers a_doing_it_wrong()notice for any unrecognized keys. It also validates thatmodule_dependenciesis an array of strings.When
WP_Script_Modules::get_import_map()is called, it now efficiently traverses the dependency tree of all enqueued classic scripts to find any associated module dependencies. These modules are then added to the import map, making them available for dynamic imports within the classic scripts.The usage looks like this:
Old Description
This change proposes allowing classic scripts to add script module dependencies.
Classic scripts can add module dependencies like
array( 'type' => 'module', 'id' => 'example-module-id' ), where classic script dependencies are simple strings, e.g.'wp-i18n'.In order for a classic script to have access to a script module, the script module must appear in the importmap so that it can be accessed by its module identifier from the classic script in a dynamic import.
For a classic script to depend on a module, it must declare that dependency and must be enqueued before the importmap is printed. When the script modules import map is printed, it inspects enqueued scripts to search for module dependencies and includes those dependencies in the import map. Import maps must be printed before any modulepreloads or any script module tags, and only one can be printed (although the specification has changed to allow multiple import maps).
The implementation overrides the
WP_Dependencies::addmethod inWP_Scripts.addis is the main method that handles script registration. The subclassed implementation is used to partition the provided dependencies array into classic script dependencies and script module dependencies. The classic script dependencies are passed on toWP_Dependencies::addalong with the rest of the arguments. The module dependencies are attached to the script as extra datamodule_deps.When the script modules importmap is printed, it scans through the registered classic scripts for enqueued scripts with
module_depsand adds those modules to the import map.Script modules in the import map will be available for classic scripts to use via dynamic
import().The dependencies look like this:
Builds on #8009.The implementation here is now independent.Trac ticket: https://core.trac.wordpress.org/ticket/61500
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.