This content originally appeared on Zach Leatherman and was authored by Zach Leatherman
By now you may be familiar with <is-land>
, the Eleventy utility for islands and partial hydration.
One of the tricks <is-land>
uses to delay initialization of Web Components’ custom elements nested as child content is that it iterates over any :not(:defined)
nodes and renames the elements to a non-upgradable tag name (<my-component>
becomes <is-land--my-component>
before <my-component>
is defined in the custom element registry via customElements.define
).
This works pretty well: it doesn’t require knowledge of which web components exist or may exist at some point in the future and leaves other HTML as is. Though I will admit it is a tad bit unexpected to folks that have tied their pre-hydrated CSS to the original tag name (I’d suggest using a class
instead!).
However, some component frameworks have started adopting a community-agreed-upon draft standard: using a defer-hydration
attribute on a component to denote that the component code will instead handle lazy initialization (when the attribute is removed).
Personally, I’d love to see this as part of a web standard first-party supported in browsers without requiring any userland component code changes. The first step to make this a viable formal standard in the future is to encourage folks to adopt the community protocol in their component code today!
In fact, <is-land>
v3.0.0 now supports defer-hydration
to skip the custom element tag rename and let the component code handle deferred hydration itself. Here’s how it might work:
<is-land on:visible>
<my-component defer-hydration>
</is-land>
And then your component JavaScript:
class MyComponent extends HTMLElement {
connectedCallback() {
this.hydrate();
}
static get observedAttributes() {
return ["defer-hydration"];
}
attributeChangedCallback(name, old, value) {
// when defined it triggers an attribute change from `null` to `""`
if(name ==="defer-hydration" && value === null) {
this.hydrate();
}
}
hydrate() {
if(this.hasAttribute("defer-hydration")) {
return;
}
// Run the initialization code.
}
}
if("customElements" in window) {
customElements.define("my-component", MyComponent);
}
When the <is-land>
loading conditions are met and the island hydrates, it removes all defer-hydration
attributes from nested child elements. This is provided for-free by the <is-land>
utility.
The defer-hydration
attribute removal then triggers the attributeChangedCallback
which runs the hydrate()
method.
- Live Demo on
is-land.11ty.dev
- Special thanks to Doug Parker (of the Angular team) for suggesting this for
<is-land>
on Mastodon!
This content originally appeared on Zach Leatherman and was authored by Zach Leatherman
Zach Leatherman | Sciencx (2022-11-15T00:00:00+00:00) Use defer-hydration in your Web Components for… well, deferred hydration.. Retrieved from https://www.scien.cx/2022/11/15/use-defer-hydration-in-your-web-components-for-well-deferred-hydration/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.