Overview
Currently, the js.compiled property of code components and asset libraries imports React/Preact code from bare module specifiers: e.g., react/jsx-runtime, preact/hooks, etc.
When the browser loads the JS file (aka the astro island's component-url) of the code component, it needs to know where to get that Preact code from.
Proposed resolution
The following options are ordered from least scope to most scope. Any option is acceptable for resolving this issue. If we only do option 1 or option 2 for now, we can do whatever remains to get us to option 3 in a less urgent follow-up.
Option 1
Within XbAssetLibraryTrait::getJs(), do string/regex replacements to change js.compiled before it's written to disk. Change the bare module specifiers to the corresponding paths to the files in ui/lib/astro-hydration/dist. See https://git.drupalcode.org/project/experience_builder/-/merge_requests/3... for prior art in the PoC.
Option 2
Do the same as option 1, but instead of changing the contents of the JS that gets written to disk, add those replacements to an import map. Use https://www.drupal.org/project/importmaps or https://www.drupal.org/project/importmap if that's helpful, but we can also for now assume that only our import map is needed and not worry about merging with import maps from other Drupal modules. Browser support for multiple import maps is coming soon, which might obsolete the importmap(s) Drupal modules.
Option 3
Do the same as option 2, but make the import map map the React packages to preact/compat from https://esm.sh. Along with this, change ui/lib/astro-hydration/astro.config.mjs to use React instead of Preact and to externalize React.
Note that the scope of this issue only needs to cover React/Preact itself, not other 3rd party packages. #3500761: Allow code components to import from npm packages is a separate issue for the latter.
User interface changes
| Comment | File | Size | Author |
|---|---|---|---|
| #6 | Screenshot from 2025-02-21 15-09-22.png | 138.91 KB | larowlan |
Issue fork experience_builder-3507567
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
effulgentsia commentedComment #3
effulgentsia commentedComment #4
larowlanComment #6
larowlanIn my local testing this is allowing hydration although props aren't being passed through properly.
Ran out of time to work out what is wrong with props:
Here's my component
And my Javascript component:
Here's how it is rendered in the island
You can see the name prop is being set. but not being rendered properly
Screenshot showing 3 placed instances

Comment #7
larowlanIgnore the default value in the component above
{name} = 'Steve'if I fix that to{name = 'Steve' }I get a name to show, but it's always Steve, i.e. the props still don't get passed in.Comment #8
effulgentsia commentedAstro receives props as tuples, so this would need to be
props="{"name":[0,"bobby"]}". #3505993: Code Components as Block Overrides, step 1 contains a more generic fix for non-scalar prop values by using 'raw' instead of 0. In any case, this is pre-existing in 0.x and not this MR's responsibility to fix.Comment #10
effulgentsia commentedThis is a really nice implementation of option #2. Merged to 0.x.
Comment #11
balintbrewsI made #3508562: Fix code component prop serialization in Astro islands for #7 and #8, I thought it would be useful to land that sooner.
Comment #12
wim leersVery nice use of the
html_response.attachments_processorinfrastructure, in two ways:import_maps) and mapping it to a pre-existing one provided by core (html_head), which then allows it to transparently work everywhere!(This is the same overall strategy that BigPipe in core uses.)
This merits being documented in #3500945: Documentation for code components.
Comment #13
nagwani commented