feat: add hydration deferal to FAST #6403
Labels
area:fast-element
Pertains to fast-element
area:ssr
Pertains to SSR.
feature
A new feature
task
A task that's part of a body of feature work.
Milestone
🙋 Feature Request
FAST should support deferring element hydration for components rendered via the SSR renderer. Doing so will allow client-side applications to control the order and timing of element rendering, ensuring context / DI resolutions are timed correctly and that any async component fetching can performed prior to template rendering.
I propose aligning to the
defer-hydration
community protocol proposal. It defines a single boolean attribute, with removal of that attribute signaling to the element controller that the component should be hydrated.What is Hydration, exactly?
Hydration is generally considered the taking-over of sever-rendered HTML by the client-side application. In component systems other than Web Components, hydration generally constructs component instances and runs any connection lifecycle hooks.
Web components are a little more complicated. Construction happens when the component is upgraded, and connectedCallback is invoked when the element is connected, regardless of the "hydration" state of the component. That means that both of these callbacks will be invoked prior to hydration. Historically, FAST has rendered the template during FASTElement.connectedCallback so many components make assumptions about template connectedness at that time, so this new behavior will likely require refactoring of components if hydration deferal is necessary for the SSR implementation.
Discussion Points
Because component constructors and connectedCallback can be invoked prior to hydration, a few questions are worth considering.
ElementController.addStyles()
add styles to the view before hydration?Implementation
FAST-SSR
@microsoft/fast-ssr
will yield thedefer-hydration
attribute during custom element rendering. We can make this behavior configurable, if necessary.FAST-Element
ElementController will need to guard against rendering it's template and attaching main styles in cases where it detects the
defer-hydration
attribute during connection. This will require a slight refactoring the ElementController.To detect removal of the
defer-hydration
attribute, there are two options:observedAttributes
andattributeChangedCallback()
By observing the
defer-hydration
attribute, the ElementController can be notified when thedefer-hydration
attribute is removed, performing any hydration steps necessary. This will be performant but comes with two slight disadvantages:super.attributeChangedCallback()
is not invoked, FASTElement will fail to hydrate.Mutation Observer
FASTElement can set up a
MutationObserver
to observe only element instances for thedefer-hydration
attribute:This approach works well because observed elements are held with weak references, meaning observing them will not prevent garbage collection, and observing the attribute will not alter component callback behaviors. There are disadvantages though:
unobserve(target)
method (Disconnect single target instead of all whatwg/dom#126), so tearing down observers is complicated. Options include:defer-hydration
is removedunobserve(target)
method that disconnects and then re-observers all other targets. This would require strong references, and is likely not very performant.defer-hydration
are hydrated, at which point the observer would disconnect.The text was updated successfully, but these errors were encountered: