-
Notifications
You must be signed in to change notification settings - Fork 781
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
ssr/hydration: keep markup created by custom elements in the dom #764
Conversation
Thank you, @naltatis! Getting this merged and published is going to take me some time, but I promise to have a look at it soon after V2 is out. I can't make any promises, but I may accept this patch sooner than that and publish a new V1 minor with it. However, that is no guarantee it will be ported to V2—at least not at first. I appreciate your patience in the meantime! 🙏 |
@jorgebucaran Thanks for your response. I indeed haven't looked into the changes that are in V2. Do you think its worth checking the described usecases against the current V2 as well and create another PR for that if needed? Or do you first want to take your time with this one? |
This PR shows that things get a bit tricky when hydrating custom elements and adds extra unhappy bytes to Hyperapp. However, V2's latest beta changes the internal DOM mounting mechanism, affecting how hydration works in a way that allows us to remove built-in hydration without changing Hyperapp's surface API. Removing built-in hydration means you'd need to import a import { h, app } from "hyperapp"
import { hydrate } from "@hyperapp/rainbows"
app({
// ...,
node: hydrate(document.getElementById("app"))
}) allowing us to implement a more sophisticated hydration strategy that supports custom elements. Thoughts? |
I didn't follow the V2 changes closely, but extracting the hydration code to its own opt-in package sounds good. |
@naltatis Cool. If we extract hydration to an external package, I'll come back to see what you did here. But that will be after shipping V2. Also closing as I won't be merging these changes into core this time. Thank you! |
Wondering if you've had the time to look at this again, @jorgebucaran, or if there's now a way to hydrate? Thanks! |
For people coming from a web search, I spoke with @jorgebucaran and Hyperapp already supports hydration. Simply mount the app on a DOM tree that's identical to the DOM that gets generated by Hyperapp, and the library will take over. This PR isn't about hydration in general, it's a specific problem involving custom elements. There's no documentation on this as of writing, but @jorgebucaran told me this in Slack:
|
fixes the issue, that hyperapp throws out existing markup that is created by custom elements before the app is initialized.
In which scenarios does this matter?
shadow dom polyfill
Custom element code gets executed before hyperapp has hydrated the ssr markup. In browsers that don't support native shadow dom yet, its common to write the CEs private markup into the normal/light dom.
custom element ssr
There is no standard way to server render custom elements, but serveral frameworks or tools (skates, stencil, ssi) offer proprietary ways to prepolulate CE markup on the server side to improve seo and webperf.
I've added a condition to skip the existing-markup-cleaning-routine for custom elements in
patch()
in the firstisRecycling
run. This way existing markup that hyperapp did not expect stays intact and CE children that are explicitly stated in the view still get hydrated correctly.I first tried to do the skipping in
recycleElement
as @zaceno suggested in #757. But by doing this, hyperapp would create double markup for CE child elements that are defined in the view instead of hydrating the existing elements (see testcases).