Make WordPress Core

Opened 11 months ago

Last modified 5 months ago

#61500 new enhancement

Script Modules: Allow scripts to depend on modules

Reported by: jonsurrell's profile jonsurrell Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 6.5
Component: Script Loader Keywords: has-patch has-unit-tests
Focuses: javascript, performance Cc:

Description

WordPress supports JavaScript modules via the Script Modules API.

Classic Scripts would benefit from the use of Script Modules to take advantage of some benefits like conditional and deferred loading, but classic Scripts have no way of declaring a dependency on Script Modules.

Classic scripts can use the "dynamic" import( 'module-id' ) to import JavaScript modules, but there's currently no way to declare the dependency so that dependent modules are included in the import map, making this usage problematic in WordPress.

Ideally, Scripts should be able declare Script Module dependencies so that scripts can safely use modules.

This complements https://core.trac.wordpress.org/ticket/60647 which seeks to add more functionality to Script Modules.

Change History (8)

This ticket was mentioned in PR #8009 on WordPress/wordpress-develop by @jonsurrell.


5 months ago
#1

  • Keywords has-patch has-unit-tests added

This is a first step towards 61500, it adds a method to the script modules class to allow modules to be flagged for inclusion in the import map.

This means that a module can be flagged for inclusion and it will appear in the import map regardless of whether it's absent from the script module dependency graph.

This can be useful for developers to force modules to appear in the import map where they can be imported on the browser console. I expect this method to be used in the future so that classic scripts can create a dependency on script modules, where this new method will act the script dependency system to request that modules appear in the importmap.

Internally it uses an array: moduleId => null. The value is always null, but other values could be used, e.g. to request that it appear in the import map _and_ in module preloads the value might by moduleId => true or moduleId => 'preload'. Only null is used at this time. This would also appear as an argument to the include_in_import_map` method, but again that is not implemented at this time and only presented for consideration.

Trac ticket: https://core.trac.wordpress.org/ticket/61500

@jonsurrell commented on PR #8009:


5 months ago
#2

@luisherranz I'd love your thoughts on this.

@youknowriad @swissspidy This is one of the first pieces towards allowing scripts to depend on modules, I know that you're working on functionality that would like to leverage this. I'd appreciate your thoughts.

@jonsurrell commented on PR #8009:


5 months ago
#3

I added a test and fixed an issues where regular dependencies and "requested for inclusion" modules were being incorrectly overwritten.

@jonsurrell commented on PR #8009:


5 months ago
#4

https://github.com/WordPress/wordpress-develop/pull/8024 implements a complete system utilizing this.

I'm not too happy with the result. It requires scripts to print before the importmap which is not reliable.

It may be better to have scripts continue to declare module dependencies, but when printing the import map have the module system query enqueued scripts and print their module dependencies in the importmap.

I'll make this PR a draft while I continue to explore a complete implementation.

@luisherranz commented on PR #8009:


5 months ago
#5

@luisherranz I'd love your thoughts on this.

Code-wise, it looks good to me. The only question I have is why you decided to use an external array instead of a flag in the properties of the registered script module (like enqueue).

This ticket was mentioned in PR #8024 on WordPress/wordpress-develop by @jonsurrell.


5 months ago
#6

Allow classic scripts to depend on script modules.

This change proposes allowing a module dependencies to classic scripts.

The implementation overrides the WP_Dependencies::add method in WP_Scripts. add is 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 to WP_Dependencies::add along with the rest of the arguments. The module dependencies are attached to
the script as extra data module_deps.

When the script modules importmap is printed, it scans through the registered classic scripts for enqueued scripts with module_deps and 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:

wp_register_script_module( '@example/module', /*…*/ );
wp_enqueue_script(
        'example-classic',
        '/classic.js',

        // Dependencies array:
        array(
                // Classic script dependency, no changes.
                'classic-script-dependency',

                // Script module dependency, this form is new.
                array(
                        'type' => 'module',
                        'id' => '@example/module',
                ),
        ),
);

~Builds on https://github.com/WordPress/wordpress-develop/pull/8009.~ The implementation here is now independent.

Trac ticket: https://core.trac.wordpress.org/ticket/61500

@jonsurrell commented on PR #8009:


5 months ago
#7

I've found an approach in https://github.com/WordPress/wordpress-develop/pull/8024 that seems like a better solution and does not require this work. I'll close this PR. If folks think there's still value in adding this method we can reopen and consider it.

@jonsurrell commented on PR #8024:


5 months ago
#8

@luisherranz @youknowriad @swissspidy @gziolo I'd love to have your review on this approach to allowing classic scripts to depend on script modules.

Note: See TracTickets for help on using tickets.