-
Notifications
You must be signed in to change notification settings - Fork 15
Description
Context
Web Components have hydration or upgrade capabilities built-in.
Basic example:
<my-comp>
Loading...
</my-comp>Until <my-comp> is registered (via Javascript), the browser will show Loading....
The recent advancements in Declarative Shadow DOM
whatwg/dom#831 give us the possibility to even pre-render shadow roots with encapsulated styles.
<my-comp>
<template shadowroot="open">
<style>
.myshadowclass {
...
}
</style>
<div class="myshadowclass">
...
</div>
</template>
</my-comp>And this would be progressively enhanced by the custom element code.
Motivation
Ideally you want to have a single source code for your component that will management the pre-rending and the progressive enhancement.
This has been managed recently by "meta-frameworks" like Next.js, Nuxt or Sapper but these are very linked too the underlying technology, React, Vue and Svelte respectively.
There is an opportunity with Web Components to decouple the framework/lib used to build the components and the "meta-framework" used to orchestrate the pre-rendering and hydration.
In other words, you could have "meta-frameworks" (or 11ty plugins for that matter) that could be able to pre-render static forms of any Web Components no matter what the framework/lib was used to build them (LitElement, Stencil, or any of the 40+ others).
I think it makes sense to deal with this in user land.
Proposal
This is a proposal to get the ball rolling and discuss, in no way I think this is the perfect solution.
Define a method that SSR capable Custom Element would implement:
interface {
render_ssr() : string
}Frameworks/lib can automatically implement this so users only need to write a single render()-like method for both SSR and client side. It can provide a ssr flag for conditional rendering but this is up to the framework/lib to decide on the implementation.
"meta-frameworks" in charge of generating the static content would:
- load page (including javascript)
- discover custom-elements
- instantiate custom-element classes
- inject attrib and properties
- call
render_ssr() - stick it into place
Example
source index.html
<html>
...
Foo bar foo
<my-comp attr="true">
</my-comp>
...
</html>index.html after generation by "meta-framework" by calling render_ssr() method.
<html>
...
Foo bar foo
<my-comp attr="true">
<template shadowroot="open">
<style>
.myshadowclass {
...
}
</style>
<div class="myshadowclass">
...
</div>
</template>
</my-comp>
...
</html>Questions
How to push properties statically?
Can we use proven dot notation? Already used by many Web Component libs today.
<my-comp attr="true" .prop1="{ key: value }">
...
</my-comp>Anything in .prop1 value would be evaluated and the result would go to property prop1.
Do we need a additional constructor constructor(for_ssr: boolean)?
To give full context to Web Component right at the beginning of the instance.
It would be safer I guess to deal with side-effects related to Attributes/Properties setters.
My 2 cents