-
Notifications
You must be signed in to change notification settings - Fork 606
Description
Note This document is in progress
Updated Hydration Implementation Proposal
Current implementation of hydration requires bindings to be rationalized with either comment or attribute markers. Doing this everywhere is compute intensive and can significantly grow the HTML being delivered, is there a way to create a rationalization of bindings from initial state and the declarative template?
Proposed Markup & Developer Experience
The DSD (Declarative Shadow DOM) created by a backend service should be as light as possible, if we remove hydration markup this may look something like so:
DOM:
<my-component greeting="Hello" name="world">
<template shadowrootmode="open">
Hello world
</template>
</my-component>
<f-template name="my-component">
<template>
{{greeting}} {{name}}
</template>
</f-template>
TypeScript:
class MyElement extends FASTElement {
@attr
greeting
@attr
name
}
MyElement.defineAsync({
name: "my-component",
templateOptions: "hydrate",
});
TemplateElement.define({
name: "f-template",
});
In this simple case we have a single binding, defined as an attribute.
FAST Implementation Details
In order to achieve rationalization with DSD FAST needs to know the following:
- Initial state (attributes, properties, etc., applied to the class instance and defined on the class prototype)
- Template
- Rendered output (DSD)
During registration the class prototype should be made available with all attribute and property lookups. We might safely assume that anything that is bound in the template is either one of these if we expect reactivity.
Possible sequence of events:
- Partial definition with class created
- Template evaluated for bindings
- Initial state gathered
- if no
templateOptions
are specified, do not attempt hydration, simply render the template and attach it to shadow DOM - if
hydrate
is used immediately gather initial state from available attributes and observables - if
defer-and-hydrate
is used, wait fordefer-hydration
to be removed then gather initial state
- if no
- Render DOM in JS with
createElement
etc. - Walk the DSD and rationalize it with the rendered DOM (this needs some experimenting), throw errors when inconsistencies arise.
Possible errors:- Initial state mismatch
- Unexpected DOM nodes not matching with the template
- In a debug mode potentially report the expected DOM
- Finish hydration
Additional Complications
Acceptable Incomplete State
The potential exists for the desire for incomplete state, or, some method of determining a server only binding that is not expected to be tied to an attribute or property as it does not need to be updated, as outlined by #7133. This might mean a potential solution is that FASTElement itself leaves comment markers where certain types of mismatched DOM is expected, and to ignore the rendering of that piece.
Possible Outcomes
The investigation could result in one of (or more) potential outcomes:
- A non comment/attribute hydration markup is not feasible
- either will take too long to implement due to current core implementations that need to change
- is horrendously perf heavy negating any perf gains
- A non comment/attribute hydration markup is feasible
Future Possibilities
Using the f-template
exclusively to identify @attr
and @observable
Currently we have an implementation of a JSON schema being applied to the FAST definition of a component created when evaluating the f-template
. If we can further reconcile this with @attr
and @observable
we can determine from the f-template
alone where data can come from.
Example:
<f-template
name="my-component"
data-@attr-text="text|string"
>
<template>
{{text}}
</template>
</f-template>
Metadata
Metadata
Labels
Type
Projects
Status