Skip to content

Server-Side Rendering (SSR) API #7

@georges-gomes

Description

@georges-gomes

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions