SSR / foldkit-ssr
State the slice cannot carry
Parts: another package's state
Some state is not a field to pick. Remote's normalized store holds whatever the server read, most of which the page never shows. A part is a package's own contribution to the envelope: it captures what the plan's active Surfaces read, and restores it in the browser.
const Post = SSR.plan(App, {
id: 'post',
state: Projection.pick(App.model.route),
surfaces: [PostPageAt],
parts: [Remote.resume(Data)],
})Remote.resume sends each field the Surfaces select, through relations, each
connection with its boundaries, and the live cursors of what it sends, and
nothing else of the store. The browser requests none of it again, and the
coverage check counts those reads as sent. Every part the plan names must be in
the page and restore, or the page is refused whole. The server restores each
part from its own capture before serving, so a part that could not is refused
there (UnrestorablePart), not in a user's browser.
Static regions: parts of the page the server owns
An article body, a product description, highlighted code: a part of the page no
Message changes need not render in the browser at all, and what it reads need
not be sent. Mark it with SSR.static:
const view = (model: Model, h: HtmlBuilder<Message>) => ({
title: 'Post', // not the post's title: the browser does not have it
body: h.main(
[],
[
SSR.static('post-copy', ih => [
ih.h1([], [model.post.title]),
ih.p([], [model.post.body]),
]),
PostActionsView(model, h), // the part the browser owns
],
),
})The region renders once, on the server, with Foldkit's inert builder, so it
cannot attach a handler. The browser adopts the server's markup as it is and
never runs the render, so this plan sends neither post.title nor post.body
and the view check still passes. A region changes only with a new document;
content a Message should change belongs in a Surface. A region the browser
needs that is not in the page, say after a Message shows one, is logged and
rendered in the browser.
Markup the browser adopts: SSR.serving
SSR.serving() is true while the view call in progress is the server rendering a page (both
of render's passes), and false while the browser resumes and outside any render. It is for
a view whose element hydration leaves alone, such as a custom element's light DOM, and which
sends markup there that the browser's own code then takes over. The rich-text editor's host is
one: pass serverRendered: SSR.serving to foldkit-richtext-dom's editorAt, and the page
carries the document instead of an empty editor until the script runs.