Skip to content

Commit a82b2ad

Browse files
authored
Lazy Editor: Fix script modules loading (WordPress#73237)
1 parent 31bf1c9 commit a82b2ad

File tree

3 files changed

+87
-5
lines changed

3 files changed

+87
-5
lines changed

lib/experimental/class-wp-rest-block-editor-settings-controller.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,12 +544,31 @@ private function process_assets( $html_templates = array() ) {
544544
}
545545
}
546546

547+
// Build an import map from registered script modules.
548+
// the import map need to be dynamically extended in the frontend.
549+
$script_modules = wp_script_modules();
550+
$registered = array();
551+
$reflection = new ReflectionClass( $script_modules );
552+
$property = $reflection->getProperty( 'registered' );
553+
$property->setAccessible( true );
554+
$registered = $property->getValue( $script_modules );
555+
$import_map = array();
556+
foreach ( $registered as $id => $module ) {
557+
// Handle both array and object formats.
558+
if ( is_array( $module ) && isset( $module['src'] ) ) {
559+
$import_map[ $id ] = $module['src'];
560+
} elseif ( is_object( $module ) && isset( $module->src ) ) {
561+
$import_map[ $id ] = $module->src;
562+
}
563+
}
564+
547565
return array(
548566
'scripts' => $scripts_data,
549567
'styles' => $styles_data,
550568
'inline_scripts' => $inline_scripts,
551569
'inline_styles' => $inline_styles,
552570
'html_templates' => $html_templates,
571+
'script_modules' => $import_map,
553572
);
554573
}
555574

@@ -627,6 +646,11 @@ public function get_assets_schema() {
627646
'type' => 'object',
628647
'readonly' => true,
629648
),
649+
'script_modules' => array(
650+
'description' => __( 'Script modules to load into the import map.', 'gutenberg' ),
651+
'type' => 'object',
652+
'readonly' => true,
653+
),
630654
),
631655
);
632656

packages/asset-loader/src/index.ts

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,68 @@ type Style = {
44
version?: string;
55
media?: string;
66
};
7-
87
type InlineStyle = string | string[];
9-
108
type Script = {
119
src: string;
1210
deps?: string[];
1311
version?: string;
1412
in_footer?: boolean;
1513
};
16-
1714
type InlineScript = string | string[];
15+
type ScriptModules = Record< string, string >;
16+
17+
/**
18+
* Injects or extends the import map with new module entries.
19+
*
20+
* @param scriptModules - Object mapping module specifiers to URLs
21+
*/
22+
function injectImportMap( scriptModules: Record< string, string > ): void {
23+
if ( ! scriptModules || Object.keys( scriptModules ).length === 0 ) {
24+
return;
25+
}
26+
27+
// Find the existing import map script element
28+
const existingMapElement = document.querySelector< HTMLScriptElement >(
29+
'script#wp-importmap[type=importmap]'
30+
);
31+
32+
if ( existingMapElement ) {
33+
try {
34+
// Parse the existing import map
35+
const existingMap = JSON.parse( existingMapElement.text );
36+
37+
// Ensure the imports object exists
38+
if ( ! existingMap.imports ) {
39+
existingMap.imports = {};
40+
}
41+
42+
// Merge new imports with existing ones (new entries take precedence)
43+
existingMap.imports = {
44+
...existingMap.imports,
45+
...scriptModules,
46+
};
47+
48+
// Update the script element's content
49+
existingMapElement.text = JSON.stringify( existingMap, null, 2 );
50+
} catch ( error ) {
51+
// eslint-disable-next-line no-console
52+
console.error( 'Failed to parse or update import map:', error );
53+
}
54+
} else {
55+
// If no import map exists, create a new one
56+
const script = document.createElement( 'script' );
57+
script.type = 'importmap';
58+
script.id = 'wp-importmap';
59+
script.text = JSON.stringify(
60+
{
61+
imports: scriptModules,
62+
},
63+
null,
64+
2
65+
);
66+
document.head.appendChild( script );
67+
}
68+
}
1869

1970
function loadStylesheet( handle: string, styleData: Style ): Promise< void > {
2071
return new Promise( ( resolve ) => {
@@ -197,8 +248,14 @@ async function loadAssets(
197248
inlineScripts: Record< 'before' | 'after', Record< string, InlineScript > >,
198249
stylesData: Record< string, Style >,
199250
inlineStyles: Record< 'before' | 'after', Record< string, InlineStyle > >,
200-
htmlTemplates?: string[]
251+
htmlTemplates?: string[],
252+
scriptModules?: ScriptModules
201253
): Promise< void > {
254+
// Inject import map first so script modules can be resolved
255+
if ( scriptModules ) {
256+
injectImportMap( scriptModules );
257+
}
258+
202259
// Build dependency-ordered lists
203260
const orderedStyles = buildDependencyOrderedList( stylesData );
204261
const orderedScripts = buildDependencyOrderedList( scriptsData );

packages/lazy-editor/src/hooks/use-editor-assets.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export async function loadEditorAssets() {
2323
editorAssets.inline_scripts || { before: {}, after: {} },
2424
editorAssets.styles || {},
2525
editorAssets.inline_styles || { before: {}, after: {} },
26-
editorAssets.html_templates || []
26+
editorAssets.html_templates || [],
27+
editorAssets.script_modules || {}
2728
);
2829
};
2930

0 commit comments

Comments
 (0)