Skip to content

[progressive-hydration] conditions for first level hydration timing #30

@daKmoR

Description

@daKmoR

First Level hydration

This is a proposal for a "syntax" of conditions to trigger hydration of a component.

It has 3 separate "states":

  • server (only render it server-side => do not ship any js) [probably framework specific]
  • client (do not touch server-side and ship js) [probably framework specific]
  • hydrate (render server-side and at some point do loading! + rendering on client-side)

For server/client there are no additional "options"... but for hydrate, there are multiple modifies you could combine

Mode Option Description
server render server-side and do not hydrate (default)
client do not touch server-side and render client side
hydrate 👇 render server-side and at some point do loading + rendering on client-side
onClientLoad [1] as soon as possible
onClick [1] as you click on the element
onMedia [2] as soon as a media query is met
onVisible [2] as soon as component + optional padding becomes visible
onHover [2] as you hover over the element + optional padding (click triggers hover => touchscreens)
onIdle [3] as soon there is a free slot in the main thread
onDelay [3] after x ms

[1]: global events: implemented via a single global event handler
[2]: element events: every element needs its own event handler
[3]: modifiers: modify how/when the hydration happens AFTER all conditions are met

Hydrate condition combinations

Each of the options can be combined via && or ||.

Example Description
loading="server" non interactive components like layouts or graphical components (= default)
loading="hydrate" most components should hydrate as soon there is a free slot in the main thread
loading="hydrate:onIdle" same as 👆
loading="hydrate:onClientLoad" above the fold element that should become interactive as soon as possible
loading="hydrate:onMedia('(max-width: 320px)')" mobile burger menu that triggers a drawer for navigation (only hydrate on screens smaller then 320p)
loading="hydrate:onMedia('(min-width: 640px)') && onClick" chart that only becomes interactive on desktop after a click
loading="hydrate:onMedia('(prefers-reduced-motion: no-preference)') && onClick" a visual animation that plays on click only if there is no prefers-reduced-motion
loading="hydrate:onVisible && onIdle" heavy chart that becomes interactive when element becomes visible
loading="hydrate:onVisible(100px)" heavy chart that becomes interactive when element + 100px padding becomes visible
loading="client" components that do something that can not be server rendered (for example need to access cookies or localStorage)

sadly this does not prevent "useless" combinations like loading="hydrate:onVisible && onClick && onHover".

Inspired by withastro/roadmap#108 and slinkity/slinkity#20

Example of user code

<h1>Rocket Blog</h1>
<inline-notification>Do this</inline-notification>
<!-- 👆 will be only server rendered -->

<my-hero loading="hydrate:onClientLoad">
  Welcome ...
</my-hero>
<!-- 👆 server render + hydrate as soon as possible -->

<my-list loading="hydrate"></my-list>
<!-- 👆 server render + hydrate if main thread is idle  -->

<my-chart loading="hydrate:onVisible"></my-chart>
<!-- 👆 server render + hydrate as element becomes visible  -->

<my-heavy-chart loading="onVisible || onMedia('(min-width: 768px)')"></my-heavy-chart>
<!-- 👆 server render + hydrate -->
<!-- desktop: hydrate immediately (matches media query) [could add && onIdle] -->
<!-- mobile: hydrate as element becomes visible -->

<my-heavy-graph loading="hydrate:onMedia('(min-width: 768px)') && onVisible || onClick"></my-heavy-graph>
<!-- 👆 server render + hydrate -->
<!-- desktop: hydrate as element becomes visible -->
<!-- mobile: hydrate on click (to safe bandwidth) -->

<my-login loading="client"></m-login>
<!-- 👆 only client render -->

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