Server rendering
Every element renders on the server with Lit SSR and hydrates in the browser without changing what it shows. CI checks all of them on every change.
Render on the server
Render a Lit template with @lit-labs/ssr. Each element's shadow DOM is written as a declarative shadow root, so the page is styled and readable before any script loads.
import "@lit-labs/ssr/lib/install-global-dom-shim.js";
import { render } from "@lit-labs/ssr";
import { collectResult } from "@lit-labs/ssr/lib/render-result.js";
import { html } from "lit";
import "@lit-material/button";
const markup = await collectResult(render(html`<lit-material-button>Save</lit-material-button>`));>Hydrate in the browser
Load the hydration support before Lit itself, then the same components. They take over the server's markup instead of rendering again.
import "@lit-labs/ssr-client/lit-element-hydrate-support.js";
import "@lit-material/button";>Pass data as attributes
A property set on the server never reaches the markup, so the browser would start without it and the first render would differ. Components that render arrays take them as JSON attributes too: chart data, series and values, table columns and rows, dual list items, chip input values, jump links links.
html`<lit-material-table caption="People" columns=${JSON.stringify(columns)} rows=${JSON.stringify(rows)}></lit-material-table>`>What stays in the browser
The router outlet renders empty on the server (there is no location there) and fills in after hydration. Everything that measures the page, such as chart widths or the jump links' current section, settles once the browser has laid it out.
>How it's checked
CI renders every element on the server, loads the result in Chromium, hydrates it and fails if hydration throws or changes an element's text or structure: 121 cases today. This site is rendered the same way.
>