Sometimes Astro slots fail to render/hydrate

Created on 1 July 2025, 25 days ago

Overview

On a Zoom with @lauriii, he showed me how several times a page with many code component instances would occasionally show up in the canvas with blank space showing up where code component instances should be. There were no errors in the console log. Viewing the srcDoc of the iframe showed all the Astro islands there as expected, but inspecting the DOM showed that slots in some Astro islands weren't hydrated.

According to @lauriii, he's run into this frequently enough for it to be annoying, but he hasn't found reliable steps to reproduce it.

Proposed resolution

User interface changes

πŸ› Bug report
Status

Active

Version

0.0

Component

Component sources

Created by

πŸ‡ΊπŸ‡ΈUnited States effulgentsia

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @effulgentsia
  • πŸ‡¬πŸ‡§United Kingdom jessebaker

    Is this issue happening when viewing the page in the preview iframe in XB or on the front end/published version of the page?

  • πŸ‡¬πŸ‡§United Kingdom jessebaker

    @lauriii answered my question in #2 on a call: the issue is mainly happening in the XB preview. It tends to happen on pages with more components that have higher levels of nesting. He HAS seen it on the front end rendered page, but not for a long time and it is certainly more rare (probably because it is not reloading over and over like the editor iframe does).

  • πŸ‡¬πŸ‡§United Kingdom jessebaker

    I have gotten to a point where I can fairly easily reproduce this error. Unfortunately, so far, that hasn't lead to any revelations as to what the cause is, but it's certainly progress.

    The major factors in making it easy to reproduce is

    1. Have a page with 16+ JS components, with slots on. I have 8 nested inside one another and then another 8 nested inside one another below that.
    2. Have Chrome's Dev tools open
    3. Rapidly update a prop and wait until the preview updates but is missing 1 or more component.

    To make it really obvious when the rendering has failed I have given the inner most components an animation so as soon as the preview updates, if no animation plays I know that something hasn't loaded.

    As described in the IS, the issue appears to be that the element exists, but it has nothing inside it. There are no network or console errors.

    One thing of note - it happened when adding a new component that I just created for the first time. It could have just been a coincidence.

    Investigation continues.

  • πŸ‡¦πŸ‡ΊAustralia larowlan πŸ‡¦πŸ‡ΊπŸ.au GMT+10

    I wonder if the await-children attribute would make a difference?

  • πŸ‡¦πŸ‡ΊAustralia larowlan πŸ‡¦πŸ‡ΊπŸ.au GMT+10

    Opened an MR with that attribute

  • πŸ‡ͺπŸ‡ΈSpain isholgueras

    I was wondering...
    - If that's related with some kind of race condition with these code components
    - If these components must render only in the client (not in SSR) (maybe with client:only="react"
    - If we should detect/configure which code components have this client:only

    BTW, while testing this I think I've reached the limit of nested code components.

    I had 18 nested code components (with slot and prop), and it breaks in the 19th.
    "Undo last action" worked though.

  • πŸ‡¬πŸ‡§United Kingdom jessebaker

    More detailed steps to reproduce

    1. Have a page with 16+ JS components, with slots on. I have 8 nested inside one another and then another 8 nested inside one another below that.
    2. Have Chrome's Dev tools open
    3. Rapidly update a prop and wait until the preview updates but is missing 1 or more component.
    4. In Chromes dev tools I found emulating a slower (4x slow) CPU helped make this happen more often

    I used this code for my JS component (needs a slot called mySlot).

    const SlotComponent = ({mySlot}) => {
      return (
        <div className="max-w-sm min-h-36 p-2 font-bold rounded-lg text-2xl gap-4 relative mx-auto flex w-full flex-col items-center justify-center bg-[#ffc423] text-[#12285f]">
          <div className="slotc w-full bg-[hotpink]">{mySlot}</div>
        </div>
      );
    };
    export default SlotComponent;
    

    Then for the inner-most component (8 layers deep) I have used

    const AnimateInComponent = ({
      title = "Animate In Component",
    }) => {
      return (
        <div className="anim-in">
          <h3>{title}</h3>
        </div>
      );
    };
    
    export default AnimateInComponent;
    

    With this CSS

    .anim-in {
                width: 300px;
                height: 250px;
                background-color: #ffc423;
                display: flex;
                align-items: center;
                justify-content: center;
                font-size: 20px;
                animation: loopAnimation2 2s 1 alternate ease-in-out;
            }
    
            @keyframes loopAnimation2 {
                0% {
                    transform: scale(0.2) rotate(-20deg);
                }
                50% {
                 transform: scale(1.2) rotate(20deg);
                }
                100% {
                    transform: scale(1) rotate(0deg);
                }
            }
    
  • πŸ‡ΊπŸ‡ΈUnited States tedbow Ithaca, NY, USA

    phpunit test failures

  • First commit to issue fork.
  • Pipeline finished with Success
    9 days ago
    Total: 1295s
    #551311
  • Pipeline finished with Skipped
    8 days ago
    #551332
  • πŸ‡¬πŸ‡§United Kingdom jessebaker
  • πŸ‡¦πŸ‡ΊAustralia larowlan πŸ‡¦πŸ‡ΊπŸ.au GMT+10

    I think there is a minor impact to performance as a result as when the iframe swaps you can sometimes still see the astro components load in

    Should we open a follow-up to try and make the 'iframe swap' wait for the `astro:hydrate' event - alternatively we can wait until iframe.contentDocument.querySelectorAll('astro-island[ssr]') has a length of zero as that attribute is removed after hydration

Production build 0.71.5 2024