Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hydration timing issue on larger pages #10633

Open
1 task
hrmcdonald opened this issue Apr 1, 2024 · 12 comments
Open
1 task

Hydration timing issue on larger pages #10633

hrmcdonald opened this issue Apr 1, 2024 · 12 comments
Labels
- P3: minor bug An edge case that only affects very specific usage (priority) pkg: lit Related to Lit (scope)

Comments

@hrmcdonald
Copy link
Contributor

hrmcdonald commented Apr 1, 2024

Astro Info

Astro                    v4.5.9
Node                     v18.19.1
System                   macOS (arm64)
Package Manager          npm
Output                   static
Adapter                  none
Integrations             auto-import
                         @astrojs/lit
                         @astrojs/mdx
                         @astrojs/react

If this issue only occurs in one browser, which browser is a problem?

No response

Describe the Bug

On certain pages where there are both enough Javascript and enough islands to be hydrated and there is some amount of real-world network latency, it appears that some part of hydration is happening out of order.

This is specifically affecting SSR'd web components. In the scenario outlined above, even though there is a declarative shadow dom (DSD) generated server-side for each web component, the components part way down the page will be initialized but not hydrated. Next hydration happens and an error gets thrown because the component already has initialized a shadow root, so the correct DSD shadow root can no longer be adopted. This leads to the following error among many other issues as a result:

image

You can see on these components that their SSR'd shadow root is not adopted and instead left as a template. This is an issue because the DSD contains the proper content. When initialized without it, a lot of strange issues occur.

image

Timing is a key factor here. When served locally, most pages do not run into this issue. It is only once deployed that the issue begins to occur often on some larger pages. The size of the page is not a factor alone. Only when there are enough different components being loaded on a larger page (so that the JS payload size is big enough I assume).

When it does happen, it only occurs part of the way down the DOM, as if the DSD polyfill is in the middle of hydrating components and then something else initializes the remaining components before it can finish? I don't know enough about how Astro initializes content on a page to discern more here.

This is currently causing a lot of issues for us in production as for our Astro docs site it only happens in that environment. We'll need to rollback to 2.x and look into an alternative tool if this doesn't get addressed eventually.


I'll also note we never had this issue previously on Astro ~2.10.15 before updating to 4.x versions. A lot has changed since then so that might not be helpful, but I figured it was worth mentioning. It seems like changes that were made to enable view-transitions might have led to this issue.

What's the expected result?

The SSR'd DSD should be adopted by the component instead of them initializing on their own and ignoring what was SSR'd. When the issue occurs something has initialized the components without regard for the DSD template...then either the browser or DSD polyfill is trying to initialize them with the DSD template and failing. So instead of a shadow root and the DSD template, only one shadow root should be visible (indicating that the DSD template was properly adopted).

image


I have been able to make a recreation of this issue here. I cannot share our internal library, but this is a build of an test page that reliably triggers this issue under the conditions outlined in the README. If necessary, I can provide more details on this recreated build.

It might also be helpful to understand what/how some elements are getting initialized without regard for their DSD if anyone more familiar with the Astro js mechanics at play here could comment.

Link to Minimal Reproducible Example

https://github.com/hrmcdonald/astro-lit-second-declarative-shadow-root-issue

Participation

  • I am willing to submit a pull request for this issue.
@github-actions github-actions bot added the needs triage Issue needs to be triaged label Apr 1, 2024
@lilnasy
Copy link
Contributor

lilnasy commented Apr 1, 2024

Could share a project instead of the compiled result of a project?

@lilnasy lilnasy added needs repro Issue needs a reproduction and removed needs triage Issue needs to be triaged labels Apr 1, 2024
Copy link
Contributor

github-actions bot commented Apr 1, 2024

Hello @hrmcdonald. Please provide a minimal reproduction using a GitHub repository or StackBlitz. Issues marked with needs repro will be closed if they have no activity within 3 days.

@hrmcdonald
Copy link
Contributor Author

Alright @lilnasy, I've updated the reproduction repo to include src code. Our version of our internal package is included locally temporarily as we cannot publish it to a public repo. Because of this, NPM handles the deps funky, so you need to use PNPM to install. If you do though you can actually see this issue present here even in dev mode.

@lilnasy
Copy link
Contributor

lilnasy commented Apr 2, 2024

Is the involvement of those internal packages necessary for the bug to appear?

@hrmcdonald
Copy link
Contributor Author

hrmcdonald commented Apr 2, 2024

No, this will occur with any SSR'd Lit web component. Even ones declared within the Astro project. Because it only seems to occur after a certain amount of JS is being loaded I bundled our components to make recreation easier (and because I'm not positive what portions of more public Lit libraries like Shoelace are SSR compatible yet).

I have updated the recreation project with a local web component that also highlights why this issue matters and shows you live on the DOM where the components stop hydrating from their DSD properly as the page is loading.

image

@lilnasy
Copy link
Contributor

lilnasy commented Apr 2, 2024

Do you see the error in dev, or only in production?

I cant reproduce the error in either.

@hrmcdonald
Copy link
Contributor Author

Sorry about that, I updated the included build to just bundle in those other internal deps instead of trying to configure NPM to scope the registries properly. If you clear your node_modules and try again it should install fine now.

The issue only happens when some level of network latency is introduced, so please make sure you've enabled simulated "Fast 3G" throttling to hit it reliably locally. In our real deployments it happens on much faster connections, but this extreme triggers it very consistently in our testing of the recreation at least.

@lilnasy
Copy link
Contributor

lilnasy commented Apr 2, 2024

I was able to install after updating the package.json to refer to mortar/style and one other library by file:, and I was able to run dev and build. I did not see an error in the browser console. All the components rendered "true".

@hrmcdonald
Copy link
Contributor Author

Even with network throttling enabled in the dev console? It will almost never hit the issue locally in dev mode without throttling.

Sorry, to answer your earlier question, we do see it in production on a lot of pages. We don't typically see it in dev, but extreme cases can be triggered locally in dev mode if you enable network throttling to simulate a slower connection so the timing hits whatever is causing this.

@lilnasy
Copy link
Contributor

lilnasy commented Apr 2, 2024

Thanks, I see it with "Slow 3G".

@lilnasy lilnasy added pkg: lit Related to Lit (scope) - P3: minor bug An edge case that only affects very specific usage (priority) and removed needs repro Issue needs a reproduction labels Apr 2, 2024
@hrmcdonald
Copy link
Contributor Author

You can probably up the number of times it loops to trigger it on faster connections too. It's some combination of:

  • amount of content on the page to be hydrated
  • amount of JS being loaded
  • connection speed

that all account into whatever race condition is happening here.

@hrmcdonald
Copy link
Contributor Author

Is there any chance someone could point me in a direction to start looking into this one? This is still affecting nearly all of our pages in production. I likely won't be able to identify a fix alone, but would like to take a stab and hunting for some more insights and potential issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
- P3: minor bug An edge case that only affects very specific usage (priority) pkg: lit Related to Lit (scope)
Projects
None yet
Development

No branches or pull requests

2 participants