From 4b71c038d570541c07bb9c2392c57e0010d29715 Mon Sep 17 00:00:00 2001
From: Alex Bronstein <12581-effulgentsia@users.noreply.drupalcode.org>
Date: Tue, 25 Feb 2025 20:20:15 -0800
Subject: [PATCH 1/2] Render block astro islands

---
 src/Element/AstroIsland.php | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/Element/AstroIsland.php b/src/Element/AstroIsland.php
index c72ca21401..bab88201ae 100644
--- a/src/Element/AstroIsland.php
+++ b/src/Element/AstroIsland.php
@@ -164,6 +164,18 @@ final class AstroIsland extends RenderElementBase {
         props="{{ __aie_props }}"
         ssr="" client="only"
         opts="{{ __aie_opts }}">';
+
+    // Reduce layout shift by blocking further document rendering until the
+    // renderer-url and component-url scripts are loaded, so that fetching them
+    // doesn't add delay between a rendering with the island blank and the
+    // hydrated rendering. This doesn't eliminate layout shift entirely,
+    // because with Astro's client="only" directive, Astro waits until the
+    // entire page is loaded before hydrating islands.
+    // @todo Investigate if it's possible to hydrate islands immediately
+    //   after the <astro-island> element is parsed rather than on page load.
+    $template .= '<script type="module" src="{{ __aie_renderer }}" blocking="render"></script>';
+    $template .= '<script type="module" src="{{ __aie_component_url }}" blocking="render"></script>';
+
     foreach ($slot_names as $slot_name) {
       // Prevent XSS via malicious render array.
       $escaped_slot_name = Html::escape((string) $slot_name);
-- 
GitLab


From 78d2e1bfc6609ea99def4f2fc40c0470eaf91dd1 Mon Sep 17 00:00:00 2001
From: Alex Bronstein <12581-effulgentsia@users.noreply.drupalcode.org>
Date: Wed, 26 Feb 2025 09:57:52 -0800
Subject: [PATCH 2/2] Fixed test

---
 tests/src/Kernel/DataType/ComponentTreeHydratedTest.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/src/Kernel/DataType/ComponentTreeHydratedTest.php b/tests/src/Kernel/DataType/ComponentTreeHydratedTest.php
index cfc7d04390..8de1ac5b54 100644
--- a/tests/src/Kernel/DataType/ComponentTreeHydratedTest.php
+++ b/tests/src/Kernel/DataType/ComponentTreeHydratedTest.php
@@ -905,7 +905,7 @@ HTML,
         renderer-url="::XB_DIR_BASE_URL::/ui/lib/astro-hydration/dist/client.js"
         props="{&quot;text&quot;:[&quot;raw&quot;,&quot;Hello, from a \&quot;code component\&quot;!&quot;]}"
         ssr="" client="only"
-        opts="{&quot;name&quot;:&quot;My First Code Component&quot;,&quot;value&quot;:&quot;preact&quot;}"></astro-island><!-- xb-end-uuid-js-component --><!-- xb-start-uuid-last-in-tree --><div  data-component-id="xb_test_sdc:props-no-slots" style="font-family: Helvetica, Arial, sans-serif; width: 100%; height: 100vh; background-color: #f5f5f5; display: flex; justify-content: center; align-items: center; flex-direction: column; text-align: center; padding: 20px; box-sizing: border-box;">
+        opts="{&quot;name&quot;:&quot;My First Code Component&quot;,&quot;value&quot;:&quot;preact&quot;}"><script type="module" src="::XB_DIR_BASE_URL::/ui/lib/astro-hydration/dist/client.js" blocking="render"></script><script type="module" src="::SITE_DIR_BASE_URL::/files/astro-island/STNRn46UCAs1xJCb2kgPiEOEZp0R24B5qjtHOsyYT-g.js" blocking="render"></script></astro-island><!-- xb-end-uuid-js-component --><!-- xb-start-uuid-last-in-tree --><div  data-component-id="xb_test_sdc:props-no-slots" style="font-family: Helvetica, Arial, sans-serif; width: 100%; height: 100vh; background-color: #f5f5f5; display: flex; justify-content: center; align-items: center; flex-direction: column; text-align: center; padding: 20px; box-sizing: border-box;">
   <h1 style="font-size: 3em; margin: 0.5em 0; color: #333;"><!-- xb-prop-start-uuid-last-in-tree/heading -->Hello, from slot &lt;LAST ONE&gt;!<!-- xb-prop-end-uuid-last-in-tree/heading --></h1>
 </div>
 <!-- xb-end-uuid-last-in-tree --><!-- xb-slot-end-uuid-level-2/the_body -->
-- 
GitLab