Bundle / foldkit-bundle
Bodies that load on demand: Bundle.lazy
A bundle's declaration is what the parent Schema and the boot need: Model,
Message, args, init, and the subscriptions, resources and helpers
Foldkit wires at boot. Its update and view can live in a chunk that loads
on the first Message inside the bundle:
const Upload = Bundle.lazy(
{
name: 'Upload',
Model: UploadModel,
Message: UploadMessage,
init: () => ({ model: { name: '', percent: 0 } }),
// Shown until the bodies load. Its handlers are what ask for them.
while: Submodel.defineView<UploadModel, UploadMessage>((model, h) =>
h.li([h.OnClick(UploadMessage.Progressed({ percent: 0 }))], [model.name]),
),
},
() => import('./upload.js').then(chunk => chunk.body),
)The chunk exports a Bundle.Body, the update and the view:
export const body: Bundle.Body<UploadModel, UploadMessage, void, never, never, void> = {
update: (model, message) => ({ model: { ...model, percent: message.percent } }),
view: Submodel.defineView<UploadModel, UploadMessage>((model, h) =>
h.li([], [`${model.name} ${model.percent}%`]),
),
}Until the bodies load, a Message reaching update leaves the Model as it is
and returns one Command, which loads them and yields the same Message again,
so nothing is lost and the Model ends where an eager bundle's would; the view
renders while, or nothing. Upload.load() loads them ahead of time, once,
and Upload.isLoaded() says whether they have. A load that fails is
forgotten, so the next Message or load() tries again. Placed, extended or
preset with with, the bundle stays lazy.
A Message that arrives before the bodies load passes through update twice:
once as the no-op that starts the load, and again when the load re-yields it.
The bundle's own Model ends where an eager bundle's would. Two things see both
passes: a Bundle.mapUpdate wrapper around the bundle, and anything that
replays recorded Messages through update after the load, such as Foldkit
DevTools time travel, which then applies that Message twice. Load the bodies
before the first interaction, as foldkit-ssr does before boot, or with
load() when the page is idle, and no Message arrives early. subscriptions, resources and
helpers stay in the declaration because Foldkit starts the first two at
boot and a helper runs synchronously; none can wait for a chunk.
test/lazy.test.ts runs this on the Foldkit runtime.
foldkit-ssr loads every lazy bundle in a page's lazy list before it
renders or boots, so a server-rendered page never shows while.