Skip to content

Commit 6daf853

Browse files
committed
Script Loader: Load the modules to the footer in classic themes
Incremental import maps fail if the import map is printed after the module scripts. This means, we should always render import maps first. This means that for classic themes, we need to move the import map and modules to the footer because we can't know before that which modules are needed. Props luisherranz, cbravobernal. Fixes #60240. git-svn-id: https://develop.svn.wordpress.org/trunk@57345 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 28fd787 commit 6daf853

2 files changed

Lines changed: 17 additions & 107 deletions

File tree

src/wp-includes/class-wp-script-modules.php

Lines changed: 17 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,12 @@ public function register( string $id, string $src, array $deps = array(), $versi
8989
'version' => $version,
9090
'enqueue' => isset( $this->enqueued_before_registered[ $id ] ),
9191
'dependencies' => $dependencies,
92-
'enqueued' => false,
93-
'preloaded' => false,
9492
);
9593
}
9694
}
9795

9896
/**
99-
* Marks the script module to be enqueued in the page the next time
100-
* `print_enqueued_script_modules` is called.
97+
* Marks the script module to be enqueued in the page.
10198
*
10299
* If a src is provided and the script module has not been registered yet, it
103100
* will be registered.
@@ -158,74 +155,49 @@ public function dequeue( string $id ) {
158155
* Adds the hooks to print the import map, enqueued script modules and script
159156
* module preloads.
160157
*
161-
* It adds the actions to print the enqueued script modules and script module
162-
* preloads to both `wp_head` and `wp_footer` because in classic themes, the
163-
* script modules used by the theme and plugins will likely be able to be
164-
* printed in the `head`, but the ones used by the blocks will need to be
165-
* enqueued in the `footer`.
166-
*
167-
* As all script modules are deferred and dependencies are handled by the
168-
* browser, the order of the script modules is not important, but it's still
169-
* better to print the ones that are available when the `wp_head` is rendered,
170-
* so the browser starts downloading those as soon as possible.
171-
*
172-
* The import map is also printed in the footer to be able to include the
173-
* dependencies of all the script modules, including the ones printed in the
158+
* In classic themes, the script modules used by the blocks are not yet known
159+
* when the `wp_head` actions is fired, so it needs to print everything in the
174160
* footer.
175161
*
176162
* @since 6.5.0
177163
*/
178164
public function add_hooks() {
179-
add_action( 'wp_head', array( $this, 'print_enqueued_script_modules' ) );
180-
add_action( 'wp_head', array( $this, 'print_script_module_preloads' ) );
181-
add_action( 'wp_footer', array( $this, 'print_enqueued_script_modules' ) );
182-
add_action( 'wp_footer', array( $this, 'print_script_module_preloads' ) );
183-
add_action( 'wp_footer', array( $this, 'print_import_map' ) );
165+
$position = wp_is_block_theme() ? 'wp_head' : 'wp_footer';
166+
add_action( $position, array( $this, 'print_import_map' ) );
167+
add_action( $position, array( $this, 'print_enqueued_script_modules' ) );
168+
add_action( $position, array( $this, 'print_script_module_preloads' ) );
184169
}
185170

186171
/**
187172
* Prints the enqueued script modules using script tags with type="module"
188173
* attributes.
189174
*
190-
* If a enqueued script module has already been printed, it will not be
191-
* printed again on subsequent calls to this function.
192-
*
193175
* @since 6.5.0
194176
*/
195177
public function print_enqueued_script_modules() {
196178
foreach ( $this->get_marked_for_enqueue() as $id => $script_module ) {
197-
if ( false === $script_module['enqueued'] ) {
198-
// Mark it as enqueued so it doesn't get enqueued again.
199-
$this->registered[ $id ]['enqueued'] = true;
200-
201-
wp_print_script_tag(
202-
array(
203-
'type' => 'module',
204-
'src' => $this->get_versioned_src( $script_module ),
205-
'id' => $id . '-js-module',
206-
)
207-
);
208-
}
179+
wp_print_script_tag(
180+
array(
181+
'type' => 'module',
182+
'src' => $this->get_versioned_src( $script_module ),
183+
'id' => $id . '-js-module',
184+
)
185+
);
209186
}
210187
}
211188

212189
/**
213190
* Prints the the static dependencies of the enqueued script modules using
214191
* link tags with rel="modulepreload" attributes.
215192
*
216-
* If a script module is marked for enqueue, it will not be preloaded. If a
217-
* preloaded script module has already been printed, it will not be printed
218-
* again on subsequent calls to this function.
193+
* If a script module is marked for enqueue, it will not be preloaded.
219194
*
220195
* @since 6.5.0
221196
*/
222197
public function print_script_module_preloads() {
223198
foreach ( $this->get_dependencies( array_keys( $this->get_marked_for_enqueue() ), array( 'static' ) ) as $id => $script_module ) {
224-
// Don't preload if it's marked for enqueue or has already been preloaded.
225-
if ( true !== $script_module['enqueue'] && false === $script_module['preloaded'] ) {
226-
// Mark it as preloaded so it doesn't get preloaded again.
227-
$this->registered[ $id ]['preloaded'] = true;
228-
199+
// Don't preload if it's marked for enqueue.
200+
if ( true !== $script_module['enqueue'] ) {
229201
echo sprintf(
230202
'<link rel="modulepreload" href="%s" id="%s">',
231203
esc_url( $this->get_versioned_src( $script_module ) ),

tests/phpunit/tests/script-modules/wpScriptModules.php

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -516,68 +516,6 @@ public function test_version_is_propagated_correctly() {
516516
$this->assertEquals( '/dep.js?ver=2.0', $preloaded_script_modules['dep'] );
517517
}
518518

519-
/**
520-
* Tests that it can print the enqueued script modules multiple times, and it
521-
* will only print the script modules that have not been printed before.
522-
*
523-
* @ticket 56313
524-
*
525-
* @covers ::register()
526-
* @covers ::enqueue()
527-
* @covers ::print_enqueued_script_modules()
528-
*/
529-
public function test_print_enqueued_script_modules_can_be_called_multiple_times() {
530-
$this->script_modules->register( 'foo', '/foo.js' );
531-
$this->script_modules->register( 'bar', '/bar.js' );
532-
$this->script_modules->enqueue( 'foo' );
533-
534-
$enqueued_script_modules = $this->get_enqueued_script_modules();
535-
$this->assertCount( 1, $enqueued_script_modules );
536-
$this->assertTrue( isset( $enqueued_script_modules['foo'] ) );
537-
538-
$this->script_modules->enqueue( 'bar' );
539-
540-
$enqueued_script_modules = $this->get_enqueued_script_modules();
541-
$this->assertCount( 1, $enqueued_script_modules );
542-
$this->assertTrue( isset( $enqueued_script_modules['bar'] ) );
543-
544-
$enqueued_script_modules = $this->get_enqueued_script_modules();
545-
$this->assertCount( 0, $enqueued_script_modules );
546-
}
547-
548-
/**
549-
* Tests that it can print the preloaded script modules multiple times, and it
550-
* will only print the script modules that have not been printed before.
551-
*
552-
* @ticket 56313
553-
*
554-
* @covers ::register()
555-
* @covers ::enqueue()
556-
* @covers ::print_script_module_preloads()
557-
*/
558-
public function test_print_preloaded_script_modules_can_be_called_multiple_times() {
559-
$this->script_modules->register( 'foo', '/foo.js', array( 'static-dep-1', 'static-dep-2' ) );
560-
$this->script_modules->register( 'bar', '/bar.js', array( 'static-dep-3' ) );
561-
$this->script_modules->register( 'static-dep-1', '/static-dep-1.js' );
562-
$this->script_modules->register( 'static-dep-3', '/static-dep-3.js' );
563-
$this->script_modules->enqueue( 'foo' );
564-
565-
$preloaded_script_modules = $this->get_preloaded_script_modules();
566-
$this->assertCount( 1, $preloaded_script_modules );
567-
$this->assertTrue( isset( $preloaded_script_modules['static-dep-1'] ) );
568-
569-
$this->script_modules->register( 'static-dep-2', '/static-dep-2.js' );
570-
$this->script_modules->enqueue( 'bar' );
571-
572-
$preloaded_script_modules = $this->get_preloaded_script_modules();
573-
$this->assertCount( 2, $preloaded_script_modules );
574-
$this->assertTrue( isset( $preloaded_script_modules['static-dep-2'] ) );
575-
$this->assertTrue( isset( $preloaded_script_modules['static-dep-3'] ) );
576-
577-
$preloaded_script_modules = $this->get_preloaded_script_modules();
578-
$this->assertCount( 0, $preloaded_script_modules );
579-
}
580-
581519
/**
582520
* Tests that a script module is not registered when calling enqueue without a
583521
* valid src.

0 commit comments

Comments
 (0)