profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/divmain/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.

neon-bindings/neon 5784

Rust bindings for writing safe and fast native Node.js modules.

timbrel/GitSavvy 1848

Full git and GitHub integration with Sublime Text 3.

divmain/js-seed 34

Start a frontend project in under 5 minutes, with full test and build infrastructure.

divmain/drydock 20

A stateful, configurable mock server built for predictable end-to-end testing and offline UI development.

divmain/recollect 14

Browser persistence assistance.

divmain/maintainerd 13

A GitHub bot to help with project maintenance.

divmain/nm-cache 11

Cache your node_modules and save your sanity!

divmain/lightyear 2

It's not falling... it's cascading, with styles.

startedarctic-hen7/perseus

started time in 2 days

Pull request review commentsalesforce/lwc-rfcs

RFC: SSR rehydration

+---
+title: SSR Rehydration
+status: DRAFTED
+created_at: 2021-08-31
+updated_at: 2021-08-31
+pr: (leave this empty until the PR is created)
+---
+
+# SSR Rehydration
+
+## Summary
+
+Whereas server-side rendering (SSR) allows a web application to be rendered into HTML on the server, rehydration involves receiving that HTML on the client and reusing the resulting DOM during initial client-side rendering (CSR).
+
+This document proposes an approach to supporting SSR rehydration in LWC.
+
+## Problem description
+
+### Motivation
+
+The motivations for SSR are [well documented](https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8) and can be boiled down to the following two points:
+
+- SSR allows search engines to easily index URLs that would otherwise be rendered on the client as part of a web application. This results in improved [SEO](https://developers.google.com/search/docs/beginner/seo-starter-guide), with all the associated benefits.
+
+- SSR can improve the perceived startup performance of a web application by reducing the time to [First Contentful Paint](https://web.dev/first-contentful-paint/). Optimizing perceived performance can have measurable impact on [conversion rates](https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/), [user satisfaction](https://www.ericsson.com/en/press-releases/2016/2/streaming-delays-mentally-taxing-for-smartphone-users-ericsson-mobility-report), and [revenue](https://www.dareboost.com/en/webperf-impacts).
+
+However, rendering on the server can itself introduce performance issues, working against the original intent. Namely, if DOM that was generated from SSR HTML is not preserved during the initial CSR, this will result in potentially expensive DOM manipulation and unwanted visual artifacts.
+
+The aim of rehydration is to avoid the client-side performance issues of a naive SSR implementation, reusing original DOM wherever possible.
+
+### The Happy Path
+
+With regard to SSR, there exists a happy path (Fig 1a) where the rendering output for a given request is identical on both the server and the client; identical VDOM is generated for the entire document in both environments.
+
+Depending upon the actual implementation, exceptions to this happy path include:
+
+- **Exception A:** One or more components are never rendered on the server (Fig 1b). Instead, a placeholder is rendered on the server, and later replaced on the client during CSR/hydration.
+  - **Example:** The page contains a cart icon with a dynamic number of items in cart.
+  - **Example:** The page contains a user avatar.
+- **Exception B:** One or more components are rendered only on the server (Fig 1c). No JS is sent to the client for these components and the original SSR'd HTML remains untouched by hydration and later client-side renders.
+  - **Example:** The page contains a footer that never changes.
+  - **Example:** The landing page is mostly static and is cached on a CDN.
+- **Exception C:** Render-critical state is changed between the time of SSR and CSR rehydration, causing an unexpected mismatch (Fig 1d).
+  - **Example:** A product price is updated after SSR but before rehydration on the client.
+  - **Example:** The CDN delivers a stale version of the landing page, which was updated after the SSR HTML was en route to the client.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig1.png" alt="Fig. 1">
+  <figcaption align = "center">
+    <b>Fig.1: the happy path and its exceptions</b>
+  </figcaption>
+</figure>
+
+## Design
+
+Several pieces need to come together to unlock rehydration. The general flow is illustrated below in figure 2.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig2.png" alt="Fig. 2" width="60%">
+  <figcaption align = "center">
+    <b>Fig.2: the proposed implementation</b>
+  </figcaption>
+</figure><br /><br />
+
+In roughly chronological order with respect to a single page request, the following steps shall be taken as part of rehydration:
+
+- As part of SSR, serialize render-critical state and bake it into the HTML response returned from the server. For each `LightningElement`, attach corresponding state to its root DOM node as `data-ssr-state`.
+
+- Rather than calling `LWC#createElement`, required that `LWC#hydrateElement` is called to mount the root Lightning Web Component on the client.
+
+- Generate server-side VDOM from the SSR HTML on the client.
+
+- As the initial client-side render progresses, extract state from `data-ssr-state` attributes, instantiate `LightningElements` with extracted state, and generate client-side VDOM.
+
+- Patch server-side VDOM with client-side VDOM.
+  
+  - Where `data-ssr-preserve` is detected, extract the server-side VDOM subtree and store for subsequent client-side renders.
+  
+  - Attach event listeners and non-serializable props.
+  
+  - Resolve unexpected inconsistencies in favor of the client-side VDOM, addressing [Exception C to the happy path](#the-happy-path). With the exception of placeholder components, this case should be rare, since the first CSR will rely on state baked into SSR as `data-ssr-state`.
+
+### `hydrateElement`
+
+In a typical LWC web application, a developer might mount their app using the following pattern:
+
+```javascript
+import { createElement } from 'lwc';
+import MyApp from './my-app';
+
+document
+  .querySelector("#root")
+  .appendChild(createElement('my-app', { is: MyApp }));
+```
+
+After the proposed change, if a developer wants to take advantage of rehydration, a developer would instead do:
+
+```javascript
+import { hydrateElement } from 'lwc';
+import MyApp from './my-app';
+
+hydrateElement(MyApp, document.querySelector('#root')); 
+```
+
+### Server-only Component Support
+
+Addressing [Exception B to the happy path](#the-happy-path) will involve a solution roughly comparable to [React server components](https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html). While the bulk of this can be implemented in user-land, at a level of abstraction above LWC, the `hydrateElement` patch implementation must support the use-case.
+
+While the initial patch progresses, each SSR VDOM node must be checked for a `data-ssr-preserve` boolean attribute. When identified, the SSR VDOM subtree rooted at that node must be preserved for subsequent client-side renders. Frameworks built on top of LWC can utilize this feature to provide server-only components.
+
+<details open>
+  <summary><b>Example:</b></summary>
+
+An LWC-based framework could provide a new `LightningServerElement` class. Its behavior and underlying implementation could be switched out at build time, as a function of the intended runtime environment.
+
+On the server, a `LightningServerElement` could behave identically to a `LightningElement` with one exception: it would attach a `data-ssr-preserve` attribute to its root node.
+
+For a client build, a Babel plugin could identify any class declaration that extends `LightningServerElement` and replace the entire declaration with `NoopElement`.  That would look something like the following:
+
+**Original Source:**
+
+```javascript
+import { api } from 'lwc';
+import { LightningServerElement } from 'some-framework';
+import { someSideEffect } from './my-app';
+
+export default class Example extends LightningServerElement {
+    @api message = 'Hello World!';
+
+    onClick () {
+      someSideEffect();
+    }
+}
+```
+
+**Server Build:**
+
+```javascript
+import { api } from 'lwc';
+import { LightningServerElement } from 'some-framework';
+import { someSideEffect } from './my-app';
+
+export default class Example extends LightningServerElement {
+    @api message = 'Hello World!';
+
+    // LightningServerElement hooks into component lifecycle:
+    //   connectedCallback () {
+    //    this.setAttribute('data-ssr-preserve', true);
+    //   }
+
+    onClick () {
+      someSideEffect();
+    }
+}
+```
+
+**SSR HTML:**
+
+```html
+<!-- ... -->
+  <x-example data-ssr-preserve>
+    <template shadowroot="open">
+      Hello World!
+    </template>
+  </x-example>
+<!-- ... -->
+```
+
+**Client Build:**
+
+```javascript
+import { api } from 'lwc';
+import { NoopElement } from 'some-framework';
+import { someSideEffect } from './my-app'; // <-- dead-code, removed with minification
+
+// The entire class declaration is replaced.
+export default class Example extends NoopElement {}
+```
+
+</details>
+
+### SSR Placeholders
+
+Implementation of placeholder components, as described in [Exception A to the happy path](#the-happy-path) should be practicable without changes to LWC, so long as unexpected subtree mismatches (Exception C) are dealt with properly.
+
+Implementation in user-land is possible with simple runtime environment detection:
+
+<details open>
+  <summary>Example:</summary>
+
+```javascript
+import { LightningElement } from 'lwc';
+import { isNodeEnv } from './my-utils';
+import tmplServerPlaceholder from './templateServer.html';
+import tmplClient from './templateClient.html';
+
+export default class ElementWithSSRPlaceholder extends LightningElement {
+    render() {
+        return this.isNodeEnv ? tmplServerPlaceholder : tmplClient;

I will re-word this. I wasn't intending to say that this approach solves exception C. I was saying that if we solve for exception C, implementing placeholder components (exception A) becomes straightforward.

divmain

comment created time in 3 days

PullRequestReviewEvent

Pull request review commentsalesforce/lwc-rfcs

RFC: SSR rehydration

+---
+title: SSR Rehydration
+status: DRAFTED
+created_at: 2021-08-31
+updated_at: 2021-08-31
+pr: (leave this empty until the PR is created)
+---
+
+# SSR Rehydration
+
+## Summary
+
+Whereas server-side rendering (SSR) allows a web application to be rendered into HTML on the server, rehydration involves receiving that HTML on the client and reusing the resulting DOM during initial client-side rendering (CSR).
+
+This document proposes an approach to supporting SSR rehydration in LWC.
+
+## Problem description
+
+### Motivation
+
+The motivations for SSR are [well documented](https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8) and can be boiled down to the following two points:
+
+- SSR allows search engines to easily index URLs that would otherwise be rendered on the client as part of a web application. This results in improved [SEO](https://developers.google.com/search/docs/beginner/seo-starter-guide), with all the associated benefits.
+
+- SSR can improve the perceived startup performance of a web application by reducing the time to [First Contentful Paint](https://web.dev/first-contentful-paint/). Optimizing perceived performance can have measurable impact on [conversion rates](https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/), [user satisfaction](https://www.ericsson.com/en/press-releases/2016/2/streaming-delays-mentally-taxing-for-smartphone-users-ericsson-mobility-report), and [revenue](https://www.dareboost.com/en/webperf-impacts).
+
+However, rendering on the server can itself introduce performance issues, working against the original intent. Namely, if DOM that was generated from SSR HTML is not preserved during the initial CSR, this will result in potentially expensive DOM manipulation and unwanted visual artifacts.
+
+The aim of rehydration is to avoid the client-side performance issues of a naive SSR implementation, reusing original DOM wherever possible.
+
+### The Happy Path
+
+With regard to SSR, there exists a happy path (Fig 1a) where the rendering output for a given request is identical on both the server and the client; identical VDOM is generated for the entire document in both environments.
+
+Depending upon the actual implementation, exceptions to this happy path include:
+
+- **Exception A:** One or more components are never rendered on the server (Fig 1b). Instead, a placeholder is rendered on the server, and later replaced on the client during CSR/hydration.
+  - **Example:** The page contains a cart icon with a dynamic number of items in cart.
+  - **Example:** The page contains a user avatar.
+- **Exception B:** One or more components are rendered only on the server (Fig 1c). No JS is sent to the client for these components and the original SSR'd HTML remains untouched by hydration and later client-side renders.
+  - **Example:** The page contains a footer that never changes.
+  - **Example:** The landing page is mostly static and is cached on a CDN.
+- **Exception C:** Render-critical state is changed between the time of SSR and CSR rehydration, causing an unexpected mismatch (Fig 1d).
+  - **Example:** A product price is updated after SSR but before rehydration on the client.
+  - **Example:** The CDN delivers a stale version of the landing page, which was updated after the SSR HTML was en route to the client.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig1.png" alt="Fig. 1">
+  <figcaption align = "center">
+    <b>Fig.1: the happy path and its exceptions</b>
+  </figcaption>
+</figure>
+
+## Design
+
+Several pieces need to come together to unlock rehydration. The general flow is illustrated below in figure 2.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig2.png" alt="Fig. 2" width="60%">
+  <figcaption align = "center">
+    <b>Fig.2: the proposed implementation</b>
+  </figcaption>
+</figure><br /><br />
+
+In roughly chronological order with respect to a single page request, the following steps shall be taken as part of rehydration:
+
+- As part of SSR, serialize render-critical state and bake it into the HTML response returned from the server. For each `LightningElement`, attach corresponding state to its root DOM node as `data-ssr-state`.
+
+- Rather than calling `LWC#createElement`, required that `LWC#hydrateElement` is called to mount the root Lightning Web Component on the client.
+
+- Generate server-side VDOM from the SSR HTML on the client.
+
+- As the initial client-side render progresses, extract state from `data-ssr-state` attributes, instantiate `LightningElements` with extracted state, and generate client-side VDOM.
+
+- Patch server-side VDOM with client-side VDOM.
+  
+  - Where `data-ssr-preserve` is detected, extract the server-side VDOM subtree and store for subsequent client-side renders.
+  
+  - Attach event listeners and non-serializable props.
+  
+  - Resolve unexpected inconsistencies in favor of the client-side VDOM, addressing [Exception C to the happy path](#the-happy-path). With the exception of placeholder components, this case should be rare, since the first CSR will rely on state baked into SSR as `data-ssr-state`.
+
+### `hydrateElement`
+
+In a typical LWC web application, a developer might mount their app using the following pattern:
+
+```javascript
+import { createElement } from 'lwc';
+import MyApp from './my-app';
+
+document
+  .querySelector("#root")
+  .appendChild(createElement('my-app', { is: MyApp }));
+```
+
+After the proposed change, if a developer wants to take advantage of rehydration, a developer would instead do:
+
+```javascript
+import { hydrateElement } from 'lwc';
+import MyApp from './my-app';
+
+hydrateElement(MyApp, document.querySelector('#root')); 
+```
+
+### Server-only Component Support

I'm happy to push this to a different proposal.

divmain

comment created time in 3 days

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentsalesforce/lwc-rfcs

RFC: SSR rehydration

+---
+title: SSR Rehydration
+status: DRAFTED
+created_at: 2021-08-31
+updated_at: 2021-08-31
+pr: (leave this empty until the PR is created)
+---
+
+# SSR Rehydration
+
+## Summary
+
+Whereas server-side rendering (SSR) allows a web application to be rendered into HTML on the server, rehydration involves receiving that HTML on the client and reusing the resulting DOM during initial client-side rendering (CSR).
+
+This document proposes an approach to supporting SSR rehydration in LWC.
+
+## Problem description
+
+### Motivation
+
+The motivations for SSR are [well documented](https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8) and can be boiled down to the following two points:
+
+- SSR allows search engines to easily index URLs that would otherwise be rendered on the client as part of a web application. This results in improved [SEO](https://developers.google.com/search/docs/beginner/seo-starter-guide), with all the associated benefits.
+
+- SSR can improve the perceived startup performance of a web application by reducing the time to [First Contentful Paint](https://web.dev/first-contentful-paint/). Optimizing perceived performance can have measurable impact on [conversion rates](https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/), [user satisfaction](https://www.ericsson.com/en/press-releases/2016/2/streaming-delays-mentally-taxing-for-smartphone-users-ericsson-mobility-report), and [revenue](https://www.dareboost.com/en/webperf-impacts).
+
+However, rendering on the server can itself introduce performance issues, working against the original intent. Namely, if DOM that was generated from SSR HTML is not preserved during the initial CSR, this will result in potentially expensive DOM manipulation and unwanted visual artifacts.
+
+The aim of rehydration is to avoid the client-side performance issues of a naive SSR implementation, reusing original DOM wherever possible.
+
+### The Happy Path
+
+With regard to SSR, there exists a happy path (Fig 1a) where the rendering output for a given request is identical on both the server and the client; identical VDOM is generated for the entire document in both environments.
+
+Depending upon the actual implementation, exceptions to this happy path include:
+
+- **Exception A:** One or more components are never rendered on the server (Fig 1b). Instead, a placeholder is rendered on the server, and later replaced on the client during CSR/hydration.
+  - **Example:** The page contains a cart icon with a dynamic number of items in cart.
+  - **Example:** The page contains a user avatar.
+- **Exception B:** One or more components are rendered only on the server (Fig 1c). No JS is sent to the client for these components and the original SSR'd HTML remains untouched by hydration and later client-side renders.
+  - **Example:** The page contains a footer that never changes.
+  - **Example:** The landing page is mostly static and is cached on a CDN.
+- **Exception C:** Render-critical state is changed between the time of SSR and CSR rehydration, causing an unexpected mismatch (Fig 1d).
+  - **Example:** A product price is updated after SSR but before rehydration on the client.
+  - **Example:** The CDN delivers a stale version of the landing page, which was updated after the SSR HTML was en route to the client.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig1.png" alt="Fig. 1">
+  <figcaption align = "center">
+    <b>Fig.1: the happy path and its exceptions</b>
+  </figcaption>
+</figure>
+
+## Design
+
+Several pieces need to come together to unlock rehydration. The general flow is illustrated below in figure 2.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig2.png" alt="Fig. 2" width="60%">
+  <figcaption align = "center">
+    <b>Fig.2: the proposed implementation</b>
+  </figcaption>
+</figure><br /><br />
+
+In roughly chronological order with respect to a single page request, the following steps shall be taken as part of rehydration:
+
+- As part of SSR, serialize render-critical state and bake it into the HTML response returned from the server. For each `LightningElement`, attach corresponding state to its root DOM node as `data-ssr-state`.
+
+- Rather than calling `LWC#createElement`, required that `LWC#hydrateElement` is called to mount the root Lightning Web Component on the client.
+
+- Generate server-side VDOM from the SSR HTML on the client.
+
+- As the initial client-side render progresses, extract state from `data-ssr-state` attributes, instantiate `LightningElements` with extracted state, and generate client-side VDOM.
+
+- Patch server-side VDOM with client-side VDOM.
+  
+  - Where `data-ssr-preserve` is detected, extract the server-side VDOM subtree and store for subsequent client-side renders.
+  
+  - Attach event listeners and non-serializable props.
+  
+  - Resolve unexpected inconsistencies in favor of the client-side VDOM, addressing [Exception C to the happy path](#the-happy-path). With the exception of placeholder components, this case should be rare, since the first CSR will rely on state baked into SSR as `data-ssr-state`.
+
+### `hydrateElement`
+
+In a typical LWC web application, a developer might mount their app using the following pattern:
+
+```javascript
+import { createElement } from 'lwc';
+import MyApp from './my-app';
+
+document
+  .querySelector("#root")
+  .appendChild(createElement('my-app', { is: MyApp }));
+```
+
+After the proposed change, if a developer wants to take advantage of rehydration, a developer would instead do:
+
+```javascript
+import { hydrateElement } from 'lwc';
+import MyApp from './my-app';
+
+hydrateElement(MyApp, document.querySelector('#root')); 
+```
+
+### Server-only Component Support
+
+Addressing [Exception B to the happy path](#the-happy-path) will involve a solution roughly comparable to [React server components](https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html). While the bulk of this can be implemented in user-land, at a level of abstraction above LWC, the `hydrateElement` patch implementation must support the use-case.
+
+While the initial patch progresses, each SSR VDOM node must be checked for a `data-ssr-preserve` boolean attribute. When identified, the SSR VDOM subtree rooted at that node must be preserved for subsequent client-side renders. Frameworks built on top of LWC can utilize this feature to provide server-only components.
+
+<details open>
+  <summary><b>Example:</b></summary>
+
+An LWC-based framework could provide a new `LightningServerElement` class. Its behavior and underlying implementation could be switched out at build time, as a function of the intended runtime environment.
+
+On the server, a `LightningServerElement` could behave identically to a `LightningElement` with one exception: it would attach a `data-ssr-preserve` attribute to its root node.
+
+For a client build, a Babel plugin could identify any class declaration that extends `LightningServerElement` and replace the entire declaration with `NoopElement`.  That would look something like the following:

Yes, this would be entirely independent of LWC, really. But documentation/ideas/examples will be important to answer: "How do I make "server components" in LWC like React has?"

divmain

comment created time in 3 days

Pull request review commentsalesforce/lwc-rfcs

RFC: SSR rehydration

+---
+title: SSR Rehydration
+status: DRAFTED
+created_at: 2021-08-31
+updated_at: 2021-08-31
+pr: (leave this empty until the PR is created)
+---
+
+# SSR Rehydration
+
+## Summary
+
+Whereas server-side rendering (SSR) allows a web application to be rendered into HTML on the server, rehydration involves receiving that HTML on the client and reusing the resulting DOM during initial client-side rendering (CSR).
+
+This document proposes an approach to supporting SSR rehydration in LWC.
+
+## Problem description
+
+### Motivation
+
+The motivations for SSR are [well documented](https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8) and can be boiled down to the following two points:
+
+- SSR allows search engines to easily index URLs that would otherwise be rendered on the client as part of a web application. This results in improved [SEO](https://developers.google.com/search/docs/beginner/seo-starter-guide), with all the associated benefits.
+
+- SSR can improve the perceived startup performance of a web application by reducing the time to [First Contentful Paint](https://web.dev/first-contentful-paint/). Optimizing perceived performance can have measurable impact on [conversion rates](https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/), [user satisfaction](https://www.ericsson.com/en/press-releases/2016/2/streaming-delays-mentally-taxing-for-smartphone-users-ericsson-mobility-report), and [revenue](https://www.dareboost.com/en/webperf-impacts).
+
+However, rendering on the server can itself introduce performance issues, working against the original intent. Namely, if DOM that was generated from SSR HTML is not preserved during the initial CSR, this will result in potentially expensive DOM manipulation and unwanted visual artifacts.
+
+The aim of rehydration is to avoid the client-side performance issues of a naive SSR implementation, reusing original DOM wherever possible.
+
+### The Happy Path
+
+With regard to SSR, there exists a happy path (Fig 1a) where the rendering output for a given request is identical on both the server and the client; identical VDOM is generated for the entire document in both environments.
+
+Depending upon the actual implementation, exceptions to this happy path include:
+
+- **Exception A:** One or more components are never rendered on the server (Fig 1b). Instead, a placeholder is rendered on the server, and later replaced on the client during CSR/hydration.
+  - **Example:** The page contains a cart icon with a dynamic number of items in cart.
+  - **Example:** The page contains a user avatar.
+- **Exception B:** One or more components are rendered only on the server (Fig 1c). No JS is sent to the client for these components and the original SSR'd HTML remains untouched by hydration and later client-side renders.
+  - **Example:** The page contains a footer that never changes.
+  - **Example:** The landing page is mostly static and is cached on a CDN.
+- **Exception C:** Render-critical state is changed between the time of SSR and CSR rehydration, causing an unexpected mismatch (Fig 1d).
+  - **Example:** A product price is updated after SSR but before rehydration on the client.
+  - **Example:** The CDN delivers a stale version of the landing page, which was updated after the SSR HTML was en route to the client.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig1.png" alt="Fig. 1">
+  <figcaption align = "center">
+    <b>Fig.1: the happy path and its exceptions</b>
+  </figcaption>
+</figure>
+
+## Design
+
+Several pieces need to come together to unlock rehydration. The general flow is illustrated below in figure 2.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig2.png" alt="Fig. 2" width="60%">
+  <figcaption align = "center">
+    <b>Fig.2: the proposed implementation</b>
+  </figcaption>
+</figure><br /><br />
+
+In roughly chronological order with respect to a single page request, the following steps shall be taken as part of rehydration:
+
+- As part of SSR, serialize render-critical state and bake it into the HTML response returned from the server. For each `LightningElement`, attach corresponding state to its root DOM node as `data-ssr-state`.
+
+- Rather than calling `LWC#createElement`, required that `LWC#hydrateElement` is called to mount the root Lightning Web Component on the client.
+
+- Generate server-side VDOM from the SSR HTML on the client.
+
+- As the initial client-side render progresses, extract state from `data-ssr-state` attributes, instantiate `LightningElements` with extracted state, and generate client-side VDOM.

My thought is that it could be present on any component in the subtree. The other approach with the same aim is to extract a state tree that mirrors the component tree during SSR, and serialize state in a single place. However, serializing the state at the root node of each component means the state is easily accessible during traversal in rehydration, which is attractive from the implementation side. Open to feedback here, if you think there are pitfalls I haven't accounted for.

divmain

comment created time in 3 days

PullRequestReviewEvent

Pull request review commentsalesforce/lwc-rfcs

RFC: SSR rehydration

+---
+title: SSR Rehydration
+status: DRAFTED
+created_at: 2021-08-31
+updated_at: 2021-08-31
+pr: (leave this empty until the PR is created)
+---
+
+# SSR Rehydration
+
+## Summary
+
+Whereas server-side rendering (SSR) allows a web application to be rendered into HTML on the server, rehydration involves receiving that HTML on the client and reusing the resulting DOM during initial client-side rendering (CSR).
+
+This document proposes an approach to supporting SSR rehydration in LWC.
+
+## Problem description
+
+### Motivation
+
+The motivations for SSR are [well documented](https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8) and can be boiled down to the following two points:
+
+- SSR allows search engines to easily index URLs that would otherwise be rendered on the client as part of a web application. This results in improved [SEO](https://developers.google.com/search/docs/beginner/seo-starter-guide), with all the associated benefits.
+
+- SSR can improve the perceived startup performance of a web application by reducing the time to [First Contentful Paint](https://web.dev/first-contentful-paint/). Optimizing perceived performance can have measurable impact on [conversion rates](https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/), [user satisfaction](https://www.ericsson.com/en/press-releases/2016/2/streaming-delays-mentally-taxing-for-smartphone-users-ericsson-mobility-report), and [revenue](https://www.dareboost.com/en/webperf-impacts).
+
+However, rendering on the server can itself introduce performance issues, working against the original intent. Namely, if DOM that was generated from SSR HTML is not preserved during the initial CSR, this will result in potentially expensive DOM manipulation and unwanted visual artifacts.
+
+The aim of rehydration is to avoid the client-side performance issues of a naive SSR implementation, reusing original DOM wherever possible.
+
+### The Happy Path
+
+With regard to SSR, there exists a happy path (Fig 1a) where the rendering output for a given request is identical on both the server and the client; identical VDOM is generated for the entire document in both environments.
+
+Depending upon the actual implementation, exceptions to this happy path include:
+
+- **Exception A:** One or more components are never rendered on the server (Fig 1b). Instead, a placeholder is rendered on the server, and later replaced on the client during CSR/hydration.
+  - **Example:** The page contains a cart icon with a dynamic number of items in cart.
+  - **Example:** The page contains a user avatar.
+- **Exception B:** One or more components are rendered only on the server (Fig 1c). No JS is sent to the client for these components and the original SSR'd HTML remains untouched by hydration and later client-side renders.
+  - **Example:** The page contains a footer that never changes.
+  - **Example:** The landing page is mostly static and is cached on a CDN.
+- **Exception C:** Render-critical state is changed between the time of SSR and CSR rehydration, causing an unexpected mismatch (Fig 1d).
+  - **Example:** A product price is updated after SSR but before rehydration on the client.
+  - **Example:** The CDN delivers a stale version of the landing page, which was updated after the SSR HTML was en route to the client.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig1.png" alt="Fig. 1">
+  <figcaption align = "center">
+    <b>Fig.1: the happy path and its exceptions</b>
+  </figcaption>
+</figure>
+
+## Design
+
+Several pieces need to come together to unlock rehydration. The general flow is illustrated below in figure 2.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig2.png" alt="Fig. 2" width="60%">
+  <figcaption align = "center">
+    <b>Fig.2: the proposed implementation</b>
+  </figcaption>
+</figure><br /><br />
+
+In roughly chronological order with respect to a single page request, the following steps shall be taken as part of rehydration:
+
+- As part of SSR, serialize render-critical state and bake it into the HTML response returned from the server. For each `LightningElement`, attach corresponding state to its root DOM node as `data-ssr-state`.
+
+- Rather than calling `LWC#createElement`, required that `LWC#hydrateElement` is called to mount the root Lightning Web Component on the client.
+
+- Generate server-side VDOM from the SSR HTML on the client.

Looking again at snabbdom documentation, this step is unnecessary. I'll make the edit.

divmain

comment created time in 3 days

PullRequestReviewEvent

Pull request review commentsalesforce/lwc-rfcs

RFC: SSR rehydration

+---
+title: SSR Rehydration
+status: DRAFTED
+created_at: 2021-08-31
+updated_at: 2021-08-31
+pr: (leave this empty until the PR is created)
+---
+
+# SSR Rehydration
+
+## Summary
+
+Whereas server-side rendering (SSR) allows a web application to be rendered into HTML on the server, rehydration involves receiving that HTML on the client and reusing the resulting DOM during initial client-side rendering (CSR).
+
+This document proposes an approach to supporting SSR rehydration in LWC.
+
+## Problem description
+
+### Motivation
+
+The motivations for SSR are [well documented](https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8) and can be boiled down to the following two points:
+
+- SSR allows search engines to easily index URLs that would otherwise be rendered on the client as part of a web application. This results in improved [SEO](https://developers.google.com/search/docs/beginner/seo-starter-guide), with all the associated benefits.
+
+- SSR can improve the perceived startup performance of a web application by reducing the time to [First Contentful Paint](https://web.dev/first-contentful-paint/). Optimizing perceived performance can have measurable impact on [conversion rates](https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/), [user satisfaction](https://www.ericsson.com/en/press-releases/2016/2/streaming-delays-mentally-taxing-for-smartphone-users-ericsson-mobility-report), and [revenue](https://www.dareboost.com/en/webperf-impacts).
+
+However, rendering on the server can itself introduce performance issues, working against the original intent. Namely, if DOM that was generated from SSR HTML is not preserved during the initial CSR, this will result in potentially expensive DOM manipulation and unwanted visual artifacts.
+
+The aim of rehydration is to avoid the client-side performance issues of a naive SSR implementation, reusing original DOM wherever possible.
+
+### The Happy Path
+
+With regard to SSR, there exists a happy path (Fig 1a) where the rendering output for a given request is identical on both the server and the client; identical VDOM is generated for the entire document in both environments.
+
+Depending upon the actual implementation, exceptions to this happy path include:
+
+- **Exception A:** One or more components are never rendered on the server (Fig 1b). Instead, a placeholder is rendered on the server, and later replaced on the client during CSR/hydration.
+  - **Example:** The page contains a cart icon with a dynamic number of items in cart.
+  - **Example:** The page contains a user avatar.
+- **Exception B:** One or more components are rendered only on the server (Fig 1c). No JS is sent to the client for these components and the original SSR'd HTML remains untouched by hydration and later client-side renders.
+  - **Example:** The page contains a footer that never changes.
+  - **Example:** The landing page is mostly static and is cached on a CDN.
+- **Exception C:** Render-critical state is changed between the time of SSR and CSR rehydration, causing an unexpected mismatch (Fig 1d).
+  - **Example:** A product price is updated after SSR but before rehydration on the client.
+  - **Example:** The CDN delivers a stale version of the landing page, which was updated after the SSR HTML was en route to the client.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig1.png" alt="Fig. 1">
+  <figcaption align = "center">
+    <b>Fig.1: the happy path and its exceptions</b>
+  </figcaption>
+</figure>
+
+## Design
+
+Several pieces need to come together to unlock rehydration. The general flow is illustrated below in figure 2.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig2.png" alt="Fig. 2" width="60%">
+  <figcaption align = "center">
+    <b>Fig.2: the proposed implementation</b>
+  </figcaption>
+</figure><br /><br />
+
+In roughly chronological order with respect to a single page request, the following steps shall be taken as part of rehydration:
+
+- As part of SSR, serialize render-critical state and bake it into the HTML response returned from the server. For each `LightningElement`, attach corresponding state to its root DOM node as `data-ssr-state`.

I don't think there's a great answer to this - it is a headache when doing SSR regardless of the framework. Explicit documentation can help. Build tooling (linting, type checking) can help. I'm open to ideas here, for sure.

divmain

comment created time in 3 days

PullRequestReviewEvent

Pull request review commentsalesforce/lwc-rfcs

RFC: SSR rehydration

+---
+title: SSR Rehydration
+status: DRAFTED
+created_at: 2021-08-31
+updated_at: 2021-08-31
+pr: (leave this empty until the PR is created)
+---
+
+# SSR Rehydration
+
+## Summary
+
+Whereas server-side rendering (SSR) allows a web application to be rendered into HTML on the server, rehydration involves receiving that HTML on the client and reusing the resulting DOM during initial client-side rendering (CSR).
+
+This document proposes an approach to supporting SSR rehydration in LWC.
+
+## Problem description
+
+### Motivation
+
+The motivations for SSR are [well documented](https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8) and can be boiled down to the following two points:
+
+- SSR allows search engines to easily index URLs that would otherwise be rendered on the client as part of a web application. This results in improved [SEO](https://developers.google.com/search/docs/beginner/seo-starter-guide), with all the associated benefits.
+
+- SSR can improve the perceived startup performance of a web application by reducing the time to [First Contentful Paint](https://web.dev/first-contentful-paint/). Optimizing perceived performance can have measurable impact on [conversion rates](https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/), [user satisfaction](https://www.ericsson.com/en/press-releases/2016/2/streaming-delays-mentally-taxing-for-smartphone-users-ericsson-mobility-report), and [revenue](https://www.dareboost.com/en/webperf-impacts).
+
+However, rendering on the server can itself introduce performance issues, working against the original intent. Namely, if DOM that was generated from SSR HTML is not preserved during the initial CSR, this will result in potentially expensive DOM manipulation and unwanted visual artifacts.
+
+The aim of rehydration is to avoid the client-side performance issues of a naive SSR implementation, reusing original DOM wherever possible.
+
+### The Happy Path
+
+With regard to SSR, there exists a happy path (Fig 1a) where the rendering output for a given request is identical on both the server and the client; identical VDOM is generated for the entire document in both environments.
+
+Depending upon the actual implementation, exceptions to this happy path include:
+
+- **Exception A:** One or more components are never rendered on the server (Fig 1b). Instead, a placeholder is rendered on the server, and later replaced on the client during CSR/hydration.
+  - **Example:** The page contains a cart icon with a dynamic number of items in cart.
+  - **Example:** The page contains a user avatar.
+- **Exception B:** One or more components are rendered only on the server (Fig 1c). No JS is sent to the client for these components and the original SSR'd HTML remains untouched by hydration and later client-side renders.
+  - **Example:** The page contains a footer that never changes.
+  - **Example:** The landing page is mostly static and is cached on a CDN.
+- **Exception C:** Render-critical state is changed between the time of SSR and CSR rehydration, causing an unexpected mismatch (Fig 1d).
+  - **Example:** A product price is updated after SSR but before rehydration on the client.
+  - **Example:** The CDN delivers a stale version of the landing page, which was updated after the SSR HTML was en route to the client.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig1.png" alt="Fig. 1">
+  <figcaption align = "center">
+    <b>Fig.1: the happy path and its exceptions</b>
+  </figcaption>
+</figure>
+
+## Design
+
+Several pieces need to come together to unlock rehydration. The general flow is illustrated below in figure 2.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig2.png" alt="Fig. 2" width="60%">
+  <figcaption align = "center">
+    <b>Fig.2: the proposed implementation</b>
+  </figcaption>
+</figure><br /><br />
+
+In roughly chronological order with respect to a single page request, the following steps shall be taken as part of rehydration:
+
+- As part of SSR, serialize render-critical state and bake it into the HTML response returned from the server. For each `LightningElement`, attach corresponding state to its root DOM node as `data-ssr-state`.
+
+- Rather than calling `LWC#createElement`, required that `LWC#hydrateElement` is called to mount the root Lightning Web Component on the client.
+
+- Generate server-side VDOM from the SSR HTML on the client.
+
+- As the initial client-side render progresses, extract state from `data-ssr-state` attributes, instantiate `LightningElements` with extracted state, and generate client-side VDOM.
+
+- Patch server-side VDOM with client-side VDOM.
+  
+  - Where `data-ssr-preserve` is detected, extract the server-side VDOM subtree and store for subsequent client-side renders.
+  
+  - Attach event listeners and non-serializable props.
+  
+  - Resolve unexpected inconsistencies in favor of the client-side VDOM, addressing [Exception C to the happy path](#the-happy-path). With the exception of placeholder components, this case should be rare, since the first CSR will rely on state baked into SSR as `data-ssr-state`.
+
+### `hydrateElement`
+
+In a typical LWC web application, a developer might mount their app using the following pattern:
+
+```javascript
+import { createElement } from 'lwc';
+import MyApp from './my-app';
+
+document
+  .querySelector("#root")
+  .appendChild(createElement('my-app', { is: MyApp }));
+```
+
+After the proposed change, if a developer wants to take advantage of rehydration, a developer would instead do:
+
+```javascript
+import { hydrateElement } from 'lwc';
+import MyApp from './my-app';
+
+hydrateElement(MyApp, document.querySelector('#root')); 
+```
+
+### Server-only Component Support
+
+Addressing [Exception B to the happy path](#the-happy-path) will involve a solution roughly comparable to [React server components](https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html). While the bulk of this can be implemented in user-land, at a level of abstraction above LWC, the `hydrateElement` patch implementation must support the use-case.
+
+While the initial patch progresses, each SSR VDOM node must be checked for a `data-ssr-preserve` boolean attribute. When identified, the SSR VDOM subtree rooted at that node must be preserved for subsequent client-side renders. Frameworks built on top of LWC can utilize this feature to provide server-only components.
+
+<details open>
+  <summary><b>Example:</b></summary>
+
+An LWC-based framework could provide a new `LightningServerElement` class. Its behavior and underlying implementation could be switched out at build time, as a function of the intended runtime environment.
+
+On the server, a `LightningServerElement` could behave identically to a `LightningElement` with one exception: it would attach a `data-ssr-preserve` attribute to its root node.
+
+For a client build, a Babel plugin could identify any class declaration that extends `LightningServerElement` and replace the entire declaration with `NoopElement`.  That would look something like the following:
+
+**Original Source:**
+
+```javascript
+import { api } from 'lwc';
+import { LightningServerElement } from 'some-framework';
+import { someSideEffect } from './my-app';
+
+export default class Example extends LightningServerElement {
+    @api message = 'Hello World!';
+
+    onClick () {
+      someSideEffect();
+    }
+}
+```
+
+**Server Build:**
+
+```javascript
+import { api } from 'lwc';
+import { LightningServerElement } from 'some-framework';
+import { someSideEffect } from './my-app';
+
+export default class Example extends LightningServerElement {
+    @api message = 'Hello World!';
+
+    // LightningServerElement hooks into component lifecycle:
+    //   connectedCallback () {
+    //    this.setAttribute('data-ssr-preserve', true);
+    //   }
+
+    onClick () {
+      someSideEffect();
+    }
+}
+```
+
+**SSR HTML:**
+
+```html
+<!-- ... -->
+  <x-example data-ssr-preserve>
+    <template shadowroot="open">
+      Hello World!
+    </template>
+  </x-example>
+<!-- ... -->
+```
+
+**Client Build:**
+
+```javascript
+import { api } from 'lwc';
+import { NoopElement } from 'some-framework';
+import { someSideEffect } from './my-app'; // <-- dead-code, removed with minification
+
+// The entire class declaration is replaced.
+export default class Example extends NoopElement {}
+```
+
+</details>
+
+### SSR Placeholders
+
+Implementation of placeholder components, as described in [Exception A to the happy path](#the-happy-path) should be practicable without changes to LWC, so long as unexpected subtree mismatches (Exception C) are dealt with properly.
+
+Implementation in user-land is possible with simple runtime environment detection:
+
+<details open>
+  <summary>Example:</summary>
+
+```javascript
+import { LightningElement } from 'lwc';
+import { isNodeEnv } from './my-utils';
+import tmplServerPlaceholder from './templateServer.html';
+import tmplClient from './templateClient.html';
+
+export default class ElementWithSSRPlaceholder extends LightningElement {
+    render() {
+        return this.isNodeEnv ? tmplServerPlaceholder : tmplClient;
+    }
+}
+```
+</details><br />
+
+Alternately, if it is desirable _not_ to ship the placeholder in the client-side bundle, one could utilize a Babel transform or `@rollup/plugin-replace` to make the necessary changes at build time.
+
+<details open>
+  <summary>Example:</summary>
+
+```javascript
+import { LightningElement } from 'lwc';
+import { isNodeEnv } from './my-utils';
+// ↶ removed from client builds during minification
+import tmplServerPlaceholder from './templateServer.html';
+import tmplClient from './templateClient.html';
+
+export default class ElementWithSSRPlaceholder extends LightningElement {
+    render() {
+        /*
+          On the server, the following line is transformed to:
+            return 'server' === 'server'
+          On the client, it is transformed to:
+            return 'client' === 'server'
+        */
+        return process.env.BUILD_TARGET === 'server'
+            ? tmplServerPlaceholder
+            : tmplClient;
+        /*
+          For client builds, further minification iterations will result in:
+            1. return 'client' === 'server' ? tmplServerPlaceholder : tmplClient
+            2. return false ? tmplServerPlaceholder : tmplClient
+            3. return tmplClient
+        */
+    }
+}
+```
+
+</details>
+
+## Alternatives
+
+### Server-Only and Placeholder Components
+
+Rather than pushing responsibility for this functionality to the next layer of abstraction, LWC could handle the entirety of this use-case natively.  For example, `@lwc/engine-server` could export a `LightningServerComponent` class that behaves as described above.
+
+Proponents for this alternative might point to the principle of least astonishment: since frameworks like React are providing a primitive for this use-case, developers might expect to see something similar in LWC when SSR support is shipped. All necessary transforms could be baked into `@lwc/rollup-plugin`, providing an out-of-the-box solution.
+
+The case against this approach mostly hinges on conforming to the existing scope of LWC. Supporting functionality beyond what is strictly required to unlock a workable solution introduces maintenance burden as well as risk that we might be asked to extend SSR functionality with additional helpers and APIs for other use cases. Providing the primitives for frameworks to implement their own solution aligns well with LWC's historical approach.
+
+### Resilience to Unexpected Changes
+
+As detailed below in the [Survey of Prior Art](#survey-of-prior-art), some web frameworks choose _not_ to be resilient to unexpected changes in state and the resulting HTML/VDOM. For example, React > 16 will no longer protect against unexpected mismatched in production mode. However, React _also_ considers complex state management out of scope for the library.
+
+For performance reasons, Vue will also not repair mismatching HTML during rehydration. However, this is less of an issue in practice, because Vue will take a snapshot of state and ship it alongside the rendered application as `window.__INITIAL_STATE__`.
+
+Most framework authors have indicated that non-support for rehydration resilience is due to performance reasons. We should measure the performance impact of SSR rehydration in a large LWC app to either 1) validate our design decision, or 2) point us in a new direction.
+
+Additionally, if we determine that the performance impact is too great, a solution will need to be devised to address [Exception A to the happy path](#the-happy-path).
+
+# Unresolved questions
+
+- **What is our approach for supporting declarative shadow DOM?**
+  + We believe that critical stakeholders will want full support here. But lack of cross-browser support for declarative shadow DOM may make this tricky.
+- **How do we handle invocations of `customElement.define` with SSR-serialized custom elements already in the DOM?**
+  + If `customElement.define` is called before `hydrateElement`, the browser will "hydrate" those elements itself, and information baked into the SSR-sourced DOM could be lost.
+  + Non-deterministic ordering of lifecycle hooks or element hydration could result in undefined behavior.
+  + If `customElement.define` is called after `hydrateElement`, hydration could be ignorant of the class backing `<x-element>`. This could result in an incomplete or incorrect hydration.
+  + Strange interactions with shadow closed mode might be an issue.
+- **What edge cases does support for Light DOM introduce?**
+- **How should constructable stylesheets be rehydrated?**
+  + Assuming no special handling, SSR may generate different HTML than is generated during CSR, possibly resulting in something like a [FOUC](https://en.wikipedia.org/wiki/Flash_of_unstyled_content) as styles are replaced.
+
+## How we teach this
+
+Much like the new functionality itself, the documentation for SSR rehydration is purely additive. We won't be changing the behavior or API of existing features.
+
+Beneficial documentation may include:
+
+- an introductory blog post, explaining the underlying implementation
+
+- a new section in the [LWC Guide](https://lwc.dev/guide/introduction), explaining the SSR-specific APIs and demonstrating how to get SSR up and running
+
+- an addition to the [LWC Recipes](https://recipes.lwc.dev/) or an example application utilizing SSR
+
+# Survey of Prior Art
+
+A handful of influential web frameworks and state management libraries were examined in relation to rehydration and adjacent concerns. The findings are summarized as follows:
+
+![0000-ssr-rehydration-fig3.png](../assets/0000-ssr-rehydration-fig3.png)

Thanks @nolanlawson! I will take a look.

divmain

comment created time in 3 days

PullRequestReviewEvent

Pull request review commentsalesforce/lwc-rfcs

RFC: SSR rehydration

+---
+title: SSR Rehydration
+status: DRAFTED
+created_at: 2021-08-31
+updated_at: 2021-08-31
+pr: (leave this empty until the PR is created)
+---
+
+# SSR Rehydration
+
+## Summary
+
+Whereas server-side rendering (SSR) allows a web application to be rendered into HTML on the server, rehydration involves receiving that HTML on the client and reusing the resulting DOM during initial client-side rendering (CSR).
+
+This document proposes an approach to supporting SSR rehydration in LWC.
+
+## Problem description
+
+### Motivation
+
+The motivations for SSR are [well documented](https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8) and can be boiled down to the following two points:
+
+- SSR allows search engines to easily index URLs that would otherwise be rendered on the client as part of a web application. This results in improved [SEO](https://developers.google.com/search/docs/beginner/seo-starter-guide), with all the associated benefits.
+
+- SSR can improve the perceived startup performance of a web application by reducing the time to [First Contentful Paint](https://web.dev/first-contentful-paint/). Optimizing perceived performance can have measurable impact on [conversion rates](https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/), [user satisfaction](https://www.ericsson.com/en/press-releases/2016/2/streaming-delays-mentally-taxing-for-smartphone-users-ericsson-mobility-report), and [revenue](https://www.dareboost.com/en/webperf-impacts).
+
+However, rendering on the server can itself introduce performance issues, working against the original intent. Namely, if DOM that was generated from SSR HTML is not preserved during the initial CSR, this will result in potentially expensive DOM manipulation and unwanted visual artifacts.
+
+The aim of rehydration is to avoid the client-side performance issues of a naive SSR implementation, reusing original DOM wherever possible.
+
+### The Happy Path
+
+With regard to SSR, there exists a happy path (Fig 1a) where the rendering output for a given request is identical on both the server and the client; identical VDOM is generated for the entire document in both environments.
+
+Depending upon the actual implementation, exceptions to this happy path include:

Should there exist another lifecycle event for when a component is attached to pre-existing DOM during rehydration?

Ideally, developers shouldn't have to differentiate between pure client-side rendering and rehydration. @divmain Do you have a use case in mind?

I have seen developers commonly abuse lifecycle events, so I may be overly cautious here. But let's say a developer wants to create a websocket connection to some backend, and they want that connection attached to an instance of a component.

connectedCallback makes sense for that. But in a non-SSR world, a component won't have any child elements when connectedCallback is invoked. In an SSR world, it would.

I can't think of an example of where that should matter, but I'm thinking Hyrum's Law may apply.

divmain

comment created time in 3 days

PullRequestReviewEvent

Pull request review commentsalesforce/lwc-rfcs

RFC: SSR rehydration

+---
+title: SSR Rehydration
+status: DRAFTED
+created_at: 2021-08-31
+updated_at: 2021-08-31
+pr: (leave this empty until the PR is created)
+---
+
+# SSR Rehydration
+
+## Summary
+
+Whereas server-side rendering (SSR) allows a web application to be rendered into HTML on the server, rehydration involves receiving that HTML on the client and reusing the resulting DOM during initial client-side rendering (CSR).
+
+This document proposes an approach to supporting SSR rehydration in LWC.
+
+## Problem description
+
+### Motivation
+
+The motivations for SSR are [well documented](https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8) and can be boiled down to the following two points:
+
+- SSR allows search engines to easily index URLs that would otherwise be rendered on the client as part of a web application. This results in improved [SEO](https://developers.google.com/search/docs/beginner/seo-starter-guide), with all the associated benefits.
+
+- SSR can improve the perceived startup performance of a web application by reducing the time to [First Contentful Paint](https://web.dev/first-contentful-paint/). Optimizing perceived performance can have measurable impact on [conversion rates](https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/), [user satisfaction](https://www.ericsson.com/en/press-releases/2016/2/streaming-delays-mentally-taxing-for-smartphone-users-ericsson-mobility-report), and [revenue](https://www.dareboost.com/en/webperf-impacts).
+
+However, rendering on the server can itself introduce performance issues, working against the original intent. Namely, if DOM that was generated from SSR HTML is not preserved during the initial CSR, this will result in potentially expensive DOM manipulation and unwanted visual artifacts.
+
+The aim of rehydration is to avoid the client-side performance issues of a naive SSR implementation, reusing original DOM wherever possible.
+
+### The Happy Path
+
+With regard to SSR, there exists a happy path (Fig 1a) where the rendering output for a given request is identical on both the server and the client; identical VDOM is generated for the entire document in both environments.
+
+Depending upon the actual implementation, exceptions to this happy path include:

As far as I understand how rehydration work in other frameworks, the 2 examples above will make the framework bails out and re-render the page from scratch. Minor differences can be recovered, like text change. But DOM structural changes can't be recovered during rehydration because it would require a full DOM diffing.

There is some variation across frameworks for how this is handled and it has changed over time. Historically, for example, React was resilient to mismatches during SSR rehydration. React 16 changed that behavior for performance reasons.

However, this isn't a binary thing (resilient vs not resilient, full DOM diffing vs complete bailtout) and we don't have to treat it that way. When considering how mismatches are handled during rehydration, the following options come to mind:

  1. Bail out of rehydration entirely when a mismatch is detected, throw away the original HTML, and force a full re-render.
  2. Handle easy mismatches (text nodes, certain attrs, etc.) falling back to number 1 for anything more extreme.
  3. Bail out of rehydration for subtrees, rooted at a mismatch.
  4. Bail out of rehydration for subtrees, rooted at the component where the mismatch occurred.
  5. Try to repair as much of the SSR-derived DOM as possible, throwing nothing away explicitly.
  6. Assume no mismatches exist, and break silently.

When you refer to full DOM diffing, I interpret that to mean #5. However, we could choose #4, and may get good mileage out of that approach.

So what I'm thinking is:

  • We detect a mismatch
  • We determine if that mismatch is easily recoverable (e.g. we have allowances for text-node mismatches)
  • If it is not easily recoverable, we determine the closest LWC ancestor to that mismatch (anywhere from the root component in a SPA to a leaf component for a small widget).
  • We invalidate the ancestor's subtree, replacing SSR-derived DOM with CSR DOM for that component subtree only.

It seems that mismatches in LWC will be either A) component-level mismatch due to non-serializable state, B) ephemeral state (e.g. current time in a text node), or C) something broke unexpectedly and we need to recover.

The approach I'm suggesting would handle case A in a reasonable way most times, without incurring horrible performance degredation. If the state for the root component of a huge tree is non-serializable, the action taken would be be roughly comparable to a full bailout, which is probably the best we can do, anyway.

If we make allowances for "easy" mismatches, case B is handled without any notable cost.

The best approach for case C is difficult to know without seeing how SSR is utilized in the real world. But, worst case, you bail out at the root level. In the best case, you bail out for part of the application, minimizing the performance impact.

divmain

comment created time in 3 days

PullRequestReviewEvent

Pull request review commentsalesforce/lwc-rfcs

RFC: SSR rehydration

+---
+title: SSR Rehydration
+status: DRAFTED
+created_at: 2021-08-31
+updated_at: 2021-08-31
+pr: (leave this empty until the PR is created)
+---
+
+# SSR Rehydration
+
+## Summary
+
+Whereas server-side rendering (SSR) allows a web application to be rendered into HTML on the server, rehydration involves receiving that HTML on the client and reusing the resulting DOM during initial client-side rendering (CSR).
+
+This document proposes an approach to supporting SSR rehydration in LWC.
+
+## Problem description
+
+### Motivation
+
+The motivations for SSR are [well documented](https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8) and can be boiled down to the following two points:
+
+- SSR allows search engines to easily index URLs that would otherwise be rendered on the client as part of a web application. This results in improved [SEO](https://developers.google.com/search/docs/beginner/seo-starter-guide), with all the associated benefits.
+
+- SSR can improve the perceived startup performance of a web application by reducing the time to [First Contentful Paint](https://web.dev/first-contentful-paint/). Optimizing perceived performance can have measurable impact on [conversion rates](https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/), [user satisfaction](https://www.ericsson.com/en/press-releases/2016/2/streaming-delays-mentally-taxing-for-smartphone-users-ericsson-mobility-report), and [revenue](https://www.dareboost.com/en/webperf-impacts).
+
+However, rendering on the server can itself introduce performance issues, working against the original intent. Namely, if DOM that was generated from SSR HTML is not preserved during the initial CSR, this will result in potentially expensive DOM manipulation and unwanted visual artifacts.
+
+The aim of rehydration is to avoid the client-side performance issues of a naive SSR implementation, reusing original DOM wherever possible.
+
+### The Happy Path
+
+With regard to SSR, there exists a happy path (Fig 1a) where the rendering output for a given request is identical on both the server and the client; identical VDOM is generated for the entire document in both environments.
+
+Depending upon the actual implementation, exceptions to this happy path include:
+
+- **Exception A:** One or more components are never rendered on the server (Fig 1b). Instead, a placeholder is rendered on the server, and later replaced on the client during CSR/hydration.

Yes, as noted in a previous comment, this needs to be rephrased. The client-side component is never rendered on the server, so it is true but misleading.

divmain

comment created time in 9 days

PullRequestReviewEvent

Pull request review commentsalesforce/lwc-rfcs

RFC: SSR rehydration

+---
+title: SSR Rehydration
+status: DRAFTED
+created_at: 2021-08-31
+updated_at: 2021-08-31
+pr: (leave this empty until the PR is created)
+---
+
+# SSR Rehydration
+
+## Summary
+
+Whereas server-side rendering (SSR) allows a web application to be rendered into HTML on the server, rehydration involves receiving that HTML on the client and reusing the resulting DOM during initial client-side rendering (CSR).
+
+This document proposes an approach to supporting SSR rehydration in LWC.
+
+## Problem description
+
+### Motivation
+
+The motivations for SSR are [well documented](https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8) and can be boiled down to the following two points:
+
+- SSR allows search engines to easily index URLs that would otherwise be rendered on the client as part of a web application. This results in improved [SEO](https://developers.google.com/search/docs/beginner/seo-starter-guide), with all the associated benefits.
+
+- SSR can improve the perceived startup performance of a web application by reducing the time to [First Contentful Paint](https://web.dev/first-contentful-paint/). Optimizing perceived performance can have measurable impact on [conversion rates](https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/), [user satisfaction](https://www.ericsson.com/en/press-releases/2016/2/streaming-delays-mentally-taxing-for-smartphone-users-ericsson-mobility-report), and [revenue](https://www.dareboost.com/en/webperf-impacts).
+
+However, rendering on the server can itself introduce performance issues, working against the original intent. Namely, if DOM that was generated from SSR HTML is not preserved during the initial CSR, this will result in potentially expensive DOM manipulation and unwanted visual artifacts.
+
+The aim of rehydration is to avoid the client-side performance issues of a naive SSR implementation, reusing original DOM wherever possible.
+
+### The Happy Path
+
+With regard to SSR, there exists a happy path (Fig 1a) where the rendering output for a given request is identical on both the server and the client; identical VDOM is generated for the entire document in both environments.
+
+Depending upon the actual implementation, exceptions to this happy path include:
+
+- **Exception A:** One or more components are never rendered on the server (Fig 1b). Instead, a placeholder is rendered on the server, and later replaced on the client during CSR/hydration.
+  - **Example:** The page contains a cart icon with a dynamic number of items in cart.
+  - **Example:** The page contains a user avatar.
+- **Exception B:** One or more components are rendered only on the server (Fig 1c). No JS is sent to the client for these components and the original SSR'd HTML remains untouched by hydration and later client-side renders.
+  - **Example:** The page contains a footer that never changes.
+  - **Example:** The landing page is mostly static and is cached on a CDN.
+- **Exception C:** Render-critical state is changed between the time of SSR and CSR rehydration, causing an unexpected mismatch (Fig 1d).
+  - **Example:** A product price is updated after SSR but before rehydration on the client.
+  - **Example:** The CDN delivers a stale version of the landing page, which was updated after the SSR HTML was en route to the client.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig1.png" alt="Fig. 1">
+  <figcaption align = "center">
+    <b>Fig.1: the happy path and its exceptions</b>
+  </figcaption>
+</figure>
+
+## Design
+
+Several pieces need to come together to unlock rehydration. The general flow is illustrated below in figure 2.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig2.png" alt="Fig. 2" width="60%">
+  <figcaption align = "center">
+    <b>Fig.2: the proposed implementation</b>
+  </figcaption>
+</figure><br /><br />
+
+In roughly chronological order with respect to a single page request, the following steps shall be taken as part of rehydration:
+
+- As part of SSR, serialize render-critical state and bake it into the HTML response returned from the server. For each `LightningElement`, attach corresponding state to its root DOM node as `data-ssr-state`.

Please correct me if I misunderstand, and perhaps the language here needs to be refined. A store could be serialized using whatever method desired on the server and rehydrated on the client before hydrateElement is called, outside of LWC altogether.

Are you looking for an LWC-provided mechanism to serialize and rehydrate state that is not defined with @api on a LightningElement?

divmain

comment created time in 9 days

PullRequestReviewEvent

Pull request review commentsalesforce/lwc-rfcs

RFC: SSR rehydration

+---
+title: SSR Rehydration
+status: DRAFTED
+created_at: 2021-08-31
+updated_at: 2021-08-31
+pr: (leave this empty until the PR is created)
+---
+
+# SSR Rehydration
+
+## Summary
+
+Whereas server-side rendering (SSR) allows a web application to be rendered into HTML on the server, rehydration involves receiving that HTML on the client and reusing the resulting DOM during initial client-side rendering (CSR).
+
+This document proposes an approach to supporting SSR rehydration in LWC.
+
+## Problem description
+
+### Motivation
+
+The motivations for SSR are [well documented](https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8) and can be boiled down to the following two points:
+
+- SSR allows search engines to easily index URLs that would otherwise be rendered on the client as part of a web application. This results in improved [SEO](https://developers.google.com/search/docs/beginner/seo-starter-guide), with all the associated benefits.
+
+- SSR can improve the perceived startup performance of a web application by reducing the time to [First Contentful Paint](https://web.dev/first-contentful-paint/). Optimizing perceived performance can have measurable impact on [conversion rates](https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/), [user satisfaction](https://www.ericsson.com/en/press-releases/2016/2/streaming-delays-mentally-taxing-for-smartphone-users-ericsson-mobility-report), and [revenue](https://www.dareboost.com/en/webperf-impacts).
+
+However, rendering on the server can itself introduce performance issues, working against the original intent. Namely, if DOM that was generated from SSR HTML is not preserved during the initial CSR, this will result in potentially expensive DOM manipulation and unwanted visual artifacts.
+
+The aim of rehydration is to avoid the client-side performance issues of a naive SSR implementation, reusing original DOM wherever possible.
+
+### The Happy Path
+
+With regard to SSR, there exists a happy path (Fig 1a) where the rendering output for a given request is identical on both the server and the client; identical VDOM is generated for the entire document in both environments.
+
+Depending upon the actual implementation, exceptions to this happy path include:
+
+- **Exception A:** One or more components are never rendered on the server (Fig 1b). Instead, a placeholder is rendered on the server, and later replaced on the client during CSR/hydration.
+  - **Example:** The page contains a cart icon with a dynamic number of items in cart.
+  - **Example:** The page contains a user avatar.
+- **Exception B:** One or more components are rendered only on the server (Fig 1c). No JS is sent to the client for these components and the original SSR'd HTML remains untouched by hydration and later client-side renders.
+  - **Example:** The page contains a footer that never changes.
+  - **Example:** The landing page is mostly static and is cached on a CDN.
+- **Exception C:** Render-critical state is changed between the time of SSR and CSR rehydration, causing an unexpected mismatch (Fig 1d).
+  - **Example:** A product price is updated after SSR but before rehydration on the client.
+  - **Example:** The CDN delivers a stale version of the landing page, which was updated after the SSR HTML was en route to the client.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig1.png" alt="Fig. 1">
+  <figcaption align = "center">
+    <b>Fig.1: the happy path and its exceptions</b>
+  </figcaption>
+</figure>
+
+## Design
+
+Several pieces need to come together to unlock rehydration. The general flow is illustrated below in figure 2.
+
+<figure>
+  <img src="../assets/0000-ssr-rehydration-fig2.png" alt="Fig. 2" width="60%">
+  <figcaption align = "center">
+    <b>Fig.2: the proposed implementation</b>
+  </figcaption>
+</figure><br /><br />
+
+In roughly chronological order with respect to a single page request, the following steps shall be taken as part of rehydration:
+
+- As part of SSR, serialize render-critical state and bake it into the HTML response returned from the server. For each `LightningElement`, attach corresponding state to its root DOM node as `data-ssr-state`.
+
+- Rather than calling `LWC#createElement`, required that `LWC#hydrateElement` is called to mount the root Lightning Web Component on the client.
+
+- Generate server-side VDOM from the SSR HTML on the client.
+
+- As the initial client-side render progresses, extract state from `data-ssr-state` attributes, instantiate `LightningElements` with extracted state, and generate client-side VDOM.
+
+- Patch server-side VDOM with client-side VDOM.
+  
+  - Where `data-ssr-preserve` is detected, extract the server-side VDOM subtree and store for subsequent client-side renders.
+  
+  - Attach event listeners and non-serializable props.
+  
+  - Resolve unexpected inconsistencies in favor of the client-side VDOM, addressing [Exception C to the happy path](#the-happy-path). With the exception of placeholder components, this case should be rare, since the first CSR will rely on state baked into SSR as `data-ssr-state`.
+
+### `hydrateElement`
+
+In a typical LWC web application, a developer might mount their app using the following pattern:
+
+```javascript
+import { createElement } from 'lwc';
+import MyApp from './my-app';
+
+document
+  .querySelector("#root")
+  .appendChild(createElement('my-app', { is: MyApp }));
+```
+
+After the proposed change, if a developer wants to take advantage of rehydration, a developer would instead do:
+
+```javascript
+import { hydrateElement } from 'lwc';
+import MyApp from './my-app';
+
+hydrateElement(MyApp, document.querySelector('#root')); 
+```
+
+### Server-only Component Support
+
+Addressing [Exception B to the happy path](#the-happy-path) will involve a solution roughly comparable to [React server components](https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html). While the bulk of this can be implemented in user-land, at a level of abstraction above LWC, the `hydrateElement` patch implementation must support the use-case.
+
+While the initial patch progresses, each SSR VDOM node must be checked for a `data-ssr-preserve` boolean attribute. When identified, the SSR VDOM subtree rooted at that node must be preserved for subsequent client-side renders. Frameworks built on top of LWC can utilize this feature to provide server-only components.
+
+<details open>
+  <summary><b>Example:</b></summary>
+
+An LWC-based framework could provide a new `LightningServerElement` class. Its behavior and underlying implementation could be switched out at build time, as a function of the intended runtime environment.
+
+On the server, a `LightningServerElement` could behave identically to a `LightningElement` with one exception: it would attach a `data-ssr-preserve` attribute to its root node.
+
+For a client build, a Babel plugin could identify any class declaration that extends `LightningServerElement` and replace the entire declaration with `NoopElement`.  That would look something like the following:
+
+**Original Source:**
+
+```javascript
+import { api } from 'lwc';
+import { LightningServerElement } from 'some-framework';
+import { someSideEffect } from './my-app';
+
+export default class Example extends LightningServerElement {
+    @api message = 'Hello World!';
+
+    onClick () {
+      someSideEffect();
+    }
+}
+```
+
+**Server Build:**
+
+```javascript
+import { api } from 'lwc';
+import { LightningServerElement } from 'some-framework';
+import { someSideEffect } from './my-app';
+
+export default class Example extends LightningServerElement {
+    @api message = 'Hello World!';
+
+    // LightningServerElement hooks into component lifecycle:
+    //   connectedCallback () {
+    //    this.setAttribute('data-ssr-preserve', true);
+    //   }
+
+    onClick () {
+      someSideEffect();
+    }
+}
+```
+
+**SSR HTML:**
+
+```html
+<!-- ... -->
+  <x-example data-ssr-preserve>
+    <template shadowroot="open">
+      Hello World!
+    </template>
+  </x-example>
+<!-- ... -->
+```
+
+**Client Build:**
+
+```javascript
+import { api } from 'lwc';
+import { NoopElement } from 'some-framework';
+import { someSideEffect } from './my-app'; // <-- dead-code, removed with minification
+
+// The entire class declaration is replaced.
+export default class Example extends NoopElement {}
+```
+
+</details>
+
+### SSR Placeholders
+
+Implementation of placeholder components, as described in [Exception A to the happy path](#the-happy-path) should be practicable without changes to LWC, so long as unexpected subtree mismatches (Exception C) are dealt with properly.
+
+Implementation in user-land is possible with simple runtime environment detection:
+
+<details open>
+  <summary>Example:</summary>
+
+```javascript
+import { LightningElement } from 'lwc';
+import { isNodeEnv } from './my-utils';
+import tmplServerPlaceholder from './templateServer.html';
+import tmplClient from './templateClient.html';
+
+export default class ElementWithSSRPlaceholder extends LightningElement {
+    render() {
+        return this.isNodeEnv ? tmplServerPlaceholder : tmplClient;
+    }
+}
+```
+</details><br />
+
+Alternately, if it is desirable _not_ to ship the placeholder in the client-side bundle, one could utilize a Babel transform or `@rollup/plugin-replace` to make the necessary changes at build time.
+
+<details open>
+  <summary>Example:</summary>
+
+```javascript
+import { LightningElement } from 'lwc';
+import { isNodeEnv } from './my-utils';
+// ↶ removed from client builds during minification
+import tmplServerPlaceholder from './templateServer.html';
+import tmplClient from './templateClient.html';
+
+export default class ElementWithSSRPlaceholder extends LightningElement {
+    render() {
+        /*
+          On the server, the following line is transformed to:
+            return 'server' === 'server'
+          On the client, it is transformed to:
+            return 'client' === 'server'
+        */
+        return process.env.BUILD_TARGET === 'server'
+            ? tmplServerPlaceholder
+            : tmplClient;
+        /*
+          For client builds, further minification iterations will result in:
+            1. return 'client' === 'server' ? tmplServerPlaceholder : tmplClient
+            2. return false ? tmplServerPlaceholder : tmplClient
+            3. return tmplClient
+        */
+    }
+}
+```
+
+</details>
+
+## Alternatives
+
+### Server-Only and Placeholder Components
+
+Rather than pushing responsibility for this functionality to the next layer of abstraction, LWC could handle the entirety of this use-case natively.  For example, `@lwc/engine-server` could export a `LightningServerComponent` class that behaves as described above.
+
+Proponents for this alternative might point to the principle of least astonishment: since frameworks like React are providing a primitive for this use-case, developers might expect to see something similar in LWC when SSR support is shipped. All necessary transforms could be baked into `@lwc/rollup-plugin`, providing an out-of-the-box solution.
+
+The case against this approach mostly hinges on conforming to the existing scope of LWC. Supporting functionality beyond what is strictly required to unlock a workable solution introduces maintenance burden as well as risk that we might be asked to extend SSR functionality with additional helpers and APIs for other use cases. Providing the primitives for frameworks to implement their own solution aligns well with LWC's historical approach.
+
+### Resilience to Unexpected Changes
+
+As detailed below in the [Survey of Prior Art](#survey-of-prior-art), some web frameworks choose _not_ to be resilient to unexpected changes in state and the resulting HTML/VDOM. For example, React > 16 will no longer protect against unexpected mismatched in production mode. However, React _also_ considers complex state management out of scope for the library.
+
+For performance reasons, Vue will also not repair mismatching HTML during rehydration. However, this is less of an issue in practice, because Vue will take a snapshot of state and ship it alongside the rendered application as `window.__INITIAL_STATE__`.
+
+Most framework authors have indicated that non-support for rehydration resilience is due to performance reasons. We should measure the performance impact of SSR rehydration in a large LWC app to either 1) validate our design decision, or 2) point us in a new direction.
+
+Additionally, if we determine that the performance impact is too great, a solution will need to be devised to address [Exception A to the happy path](#the-happy-path).
+
+# Unresolved questions
+
+- **What is our approach for supporting declarative shadow DOM?**
+  + We believe that critical stakeholders will want full support here. But lack of cross-browser support for declarative shadow DOM may make this tricky.
+- **How do we handle invocations of `customElement.define` with SSR-serialized custom elements already in the DOM?**
+  + If `customElement.define` is called before `hydrateElement`, the browser will "hydrate" those elements itself, and information baked into the SSR-sourced DOM could be lost.
+  + Non-deterministic ordering of lifecycle hooks or element hydration could result in undefined behavior.
+  + If `customElement.define` is called after `hydrateElement`, hydration could be ignorant of the class backing `<x-element>`. This could result in an incomplete or incorrect hydration.
+  + Strange interactions with shadow closed mode might be an issue.
+- **What edge cases does support for Light DOM introduce?**
+- **How should constructable stylesheets be rehydrated?**
+  + Assuming no special handling, SSR may generate different HTML than is generated during CSR, possibly resulting in something like a [FOUC](https://en.wikipedia.org/wiki/Flash_of_unstyled_content) as styles are replaced.
+
+## How we teach this
+
+Much like the new functionality itself, the documentation for SSR rehydration is purely additive. We won't be changing the behavior or API of existing features.
+
+Beneficial documentation may include:
+
+- an introductory blog post, explaining the underlying implementation
+
+- a new section in the [LWC Guide](https://lwc.dev/guide/introduction), explaining the SSR-specific APIs and demonstrating how to get SSR up and running
+
+- an addition to the [LWC Recipes](https://recipes.lwc.dev/) or an example application utilizing SSR
+
+# Survey of Prior Art
+
+A handful of influential web frameworks and state management libraries were examined in relation to rehydration and adjacent concerns. The findings are summarized as follows:
+
+![0000-ssr-rehydration-fig3.png](../assets/0000-ssr-rehydration-fig3.png)

I think that the survey should include end-to-end react frameworks, such as nextjs, blitzjs, remix, etc. The inclusion of data store libraries like redux/mobx doesn't add much value.

I'm happy to take another look. A lot of what these frameworks provide is out of scope for LWC - and live more naturally in LWR, for example. But if the survey missed some functionality that would require changes to LWC, I do want to capture that. If you can point me to anything you think might be important to consider, that'd be appreciated!

VueJS SSR does not support streaming if the app relies on context data

I can add that caveat, thanks!

React does rehydrate state, you just pass in that state as props to the base component. It just isn't opinionated on where you get that state.

I suppose that's true, although I think of that as being a solution outside of React itself.

divmain

comment created time in 9 days

PullRequestReviewEvent

Pull request review commentsalesforce/lwc-rfcs

RFC: SSR rehydration

+---
+title: SSR Rehydration
+status: DRAFTED
+created_at: 2021-08-31
+updated_at: 2021-08-31
+pr: (leave this empty until the PR is created)
+---
+
+# SSR Rehydration
+
+## Summary
+
+Whereas server-side rendering (SSR) allows a web application to be rendered into HTML on the server, rehydration involves receiving that HTML on the client and reusing the resulting DOM during initial client-side rendering (CSR).
+
+This document proposes an approach to supporting SSR rehydration in LWC.
+
+## Problem description
+
+### Motivation
+
+The motivations for SSR are [well documented](https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8) and can be boiled down to the following two points:
+
+- SSR allows search engines to easily index URLs that would otherwise be rendered on the client as part of a web application. This results in improved [SEO](https://developers.google.com/search/docs/beginner/seo-starter-guide), with all the associated benefits.
+
+- SSR can improve the perceived startup performance of a web application by reducing the time to [First Contentful Paint](https://web.dev/first-contentful-paint/). Optimizing perceived performance can have measurable impact on [conversion rates](https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/), [user satisfaction](https://www.ericsson.com/en/press-releases/2016/2/streaming-delays-mentally-taxing-for-smartphone-users-ericsson-mobility-report), and [revenue](https://www.dareboost.com/en/webperf-impacts).
+
+However, rendering on the server can itself introduce performance issues, working against the original intent. Namely, if DOM that was generated from SSR HTML is not preserved during the initial CSR, this will result in potentially expensive DOM manipulation and unwanted visual artifacts.
+
+The aim of rehydration is to avoid the client-side performance issues of a naive SSR implementation, reusing original DOM wherever possible.
+
+### The Happy Path
+
+With regard to SSR, there exists a happy path (Fig 1a) where the rendering output for a given request is identical on both the server and the client; identical VDOM is generated for the entire document in both environments.
+
+Depending upon the actual implementation, exceptions to this happy path include:
+
+- **Exception A:** One or more components are never rendered on the server (Fig 1b). Instead, a placeholder is rendered on the server, and later replaced on the client during CSR/hydration.
+  - **Example:** The page contains a cart icon with a dynamic number of items in cart.
+  - **Example:** The page contains a user avatar.
+- **Exception B:** One or more components are rendered only on the server (Fig 1c). No JS is sent to the client for these components and the original SSR'd HTML remains untouched by hydration and later client-side renders.

That's a fair question. To me, this incongruity is a natural outcome of marrying SSR (which happens outside the browser) with LWC (which "should eventually fade away to browser standards").

However, I hear you that having custom elements in the DOM without actually defining them is odd, and possibly not the right direction to go. This is a real use-case that we should either handle or explicitly not support. I'll be interested to hear what other folks have to say.

divmain

comment created time in 9 days

PullRequestReviewEvent

Pull request review commentsalesforce/lwc-rfcs

RFC: SSR rehydration

+---
+title: SSR Rehydration
+status: DRAFTED
+created_at: 2021-08-31
+updated_at: 2021-08-31
+pr: (leave this empty until the PR is created)
+---
+
+# SSR Rehydration
+
+## Summary
+
+Whereas server-side rendering (SSR) allows a web application to be rendered into HTML on the server, rehydration involves receiving that HTML on the client and reusing the resulting DOM during initial client-side rendering (CSR).
+
+This document proposes an approach to supporting SSR rehydration in LWC.
+
+## Problem description
+
+### Motivation
+
+The motivations for SSR are [well documented](https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8) and can be boiled down to the following two points:
+
+- SSR allows search engines to easily index URLs that would otherwise be rendered on the client as part of a web application. This results in improved [SEO](https://developers.google.com/search/docs/beginner/seo-starter-guide), with all the associated benefits.
+
+- SSR can improve the perceived startup performance of a web application by reducing the time to [First Contentful Paint](https://web.dev/first-contentful-paint/). Optimizing perceived performance can have measurable impact on [conversion rates](https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/), [user satisfaction](https://www.ericsson.com/en/press-releases/2016/2/streaming-delays-mentally-taxing-for-smartphone-users-ericsson-mobility-report), and [revenue](https://www.dareboost.com/en/webperf-impacts).
+
+However, rendering on the server can itself introduce performance issues, working against the original intent. Namely, if DOM that was generated from SSR HTML is not preserved during the initial CSR, this will result in potentially expensive DOM manipulation and unwanted visual artifacts.
+
+The aim of rehydration is to avoid the client-side performance issues of a naive SSR implementation, reusing original DOM wherever possible.
+
+### The Happy Path
+
+With regard to SSR, there exists a happy path (Fig 1a) where the rendering output for a given request is identical on both the server and the client; identical VDOM is generated for the entire document in both environments.
+
+Depending upon the actual implementation, exceptions to this happy path include:

Can you elaborate on how this is distinct from Exception A? I think, perhaps, the exception description can be improved and that is where the gap is. Essentially, one thing (likely a placeholder of some kind) is rendered on the server and another thing is swapped in on the client.

There are actually two ways this could go from there:

  1. You render something different on the client for the first render during rehydration. This results in an "expected mismatch" to use your words, and the patch takes care of swapping in the new content.
  2. You render the same thing on the client for the first CSR during rehydration but hook into connectedCallback and update your state to render something else asynchronously on a subsequent/early CSR.

That does bring to mind something else worth considering. Should there exist another lifecycle for when a component is attached to pre-existing DOM during rehydration? I'm not yet aware of how lifecycle hooks are widely used by LWC devs, and I wouldn't want to overload connectedCallback and break existing apps.

divmain

comment created time in 9 days

PullRequestReviewEvent
PullRequestReviewEvent