Build: Fix import map ordering in wp-build page template#76870
Build: Fix import map ordering in wp-build page template#76870lezama wants to merge 1 commit intoWordPress:trunkfrom
Conversation
|
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 If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
The generated `page-wp-admin.php` uses `import("@wordpress/boot")`
inside a regular inline script (`wp_add_inline_script`). WordPress
outputs the importmap AFTER regular footer scripts in the DOM, so
the `import()` call executes before the importmap is available. This
works by coincidence due to browser microtask timing in most setups.
However, plugins that convert scripts to `type="module"` via the
`script_loader_tag` filter (e.g., The Events Calendar via StellarWP)
disrupt this timing, causing the import to fail with:
TypeError: Failed to resolve module specifier '@wordpress/boot'
This results in a blank page with no content rendered.
Fix: Replace the fragile inline `import()` with a two-step approach:
1. The regular inline script sets boot config as a plain global
(`window.__wpBuildBootConfig`) — no module specifiers needed.
2. The `loader.js` script module (previously empty) imports
`@wordpress/boot` and calls `initSinglePage` with the config.
Script modules are guaranteed to execute after the importmap.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7703ff4 to
f954089
Compare
CGastrell
left a comment
There was a problem hiding this comment.
Tests as described, worked with Gutenberg disabled as well. The build error is not entirely correct, the pageSlugUnderscore identifier is on a different scope, but in the same global scope? Maybe you'll need to fix that in order to make the CI checks happy
Description
The
page-wp-admin.phptemplate generated by@wordpress/buildusesimport("@wordpress/boot")inside a classic inline script (wp_add_inline_script). This is incorrect:import()with a bare specifier requires the import map to already be in the DOM.In
admin_print_footer_scripts, both_wp_footer_scriptsandprint_import_mapare registered at priority 10, but_wp_footer_scriptscomes first in registration order. The classic inline script therefore always appears before the import map in the HTML output.This works by accident in most environments — browsers typically defer the specifier resolution to a microtask, by which point the import map has been parsed. But any plugin that changes execution timing (e.g. converting scripts to `type="module"` via `script_loader_tag`) breaks it:
```
TypeError: Failed to resolve module specifier '@wordpress/boot'
```
This affects all wp-build pages: Forms, Font Library, Connectors.
Fix
Two changes:
Template (
page-wp-admin.php.template): The inline script no longer callsimport(). Instead it sets the boot config as a plain global (window.__wpBuildBootConfig).Loader (
build.mjs): The previously emptyloader.jsstub now contains the actual boot code — it imports@wordpress/bootand callsinitSinglePagewith the config from the global. Sinceloader.jsis a registered script module, it executes after the import map by definition.Testing
@wordpress/buildwith awp-adminpage layout/wp-admin/themes.php?page=font-library-wp-adminand/wp-admin/options-general.php?page=options-connectors-wp-admin