Fragments

Fragments are the targets of RPC updates. When a server function runs via rpc:call, the framework re-renders any fragments in the component that reference dirty data and pushes the diff to the browser via SSE.

They are markup containers that render as other HTML elements, they can outlive the serve-side render and can be updated later.

Client-side components are already fragments, i.e.

<Example tag="p" />

would yield:

<p data-component="pages/components/Example:1">...</p>

In comparison with a tagged fragment:

<fragment tag="ul" name="a-list">
  {#each data as item}
  <li>{item}</li>
  {/each}
</fragment>

would yield:

<ul data-fragment="a-list">
  ...
</ul>

If you omit the tag attribute the element is rendered as x-fragment, which is supported by a custom-element.

The purpose of these elements is to make partial updates on the DOM, instead of patching the whole page after every request.

Fragments are great to replace, append or prepend data.

Patching options

Updates are driven by the framework, but you can configure certain aspects.

<fragment name="x" mode="prepend" limit="10" timeout="200" interval="50">
  ...
</fragment>

Thw name prop is required and it must be unique within the component.

interval (default: 0)

It will push updates every given milliseconds.

timeout (default: 50)

On timeout iterators will pause, render and resumed later.

limit (default: 100)

Once limit is reached iterators will pause, render and resumed later.

mode (default: append)

How the patching is applied: append, prepend or replace.

The framework use the above options and use the whole fragment as a template, the resulting AST is patched on the existing node on the DOM.

Options are applied to every iterator found within the fragment, try to use one iterator per fragment for simplicity.


Patching scope

Not all values are watched for patching.

Generators and promises are the only data type that can be streamed at the moment, the framework will handle all the logic to subscribe, publish and render from them.

Scoped values within the fragments are captured from their previous render, they are reused for all the upcoming renders.

They're still references and they can carry new values.

Promises

Any given promise will be awaited until the maximum execution-time is reached.

If they don't resolve on time its value will be sent after the response is sent.

Generators

Iterators produced by generators can be paused if the maximum execution-time is reached.

They are also paused by exceeding the limit of rendered items.

The framework will resume the iterators and new items will be sent to the browser.


Initial Load

On first render, fragment content is inlined into the page as a JSON snapshot so the browser can hydrate without an extra round-trip:

<script>
  window.__f = window.__f || {};
  window.__f["a-list"] = { html: "...", key: "..." };
</script>

Queued updates that arrive before the SSE connection is ready are buffered in window.__fq and flushed automatically once the socket opens.


Cross-tab Sync

Fragments with a name attribute participate in cross-tab synchronization via BroadcastChannel. When the server pushes an update, all open tabs showing the same fragment receive the patch — no extra setup required.

This works automatically for same-origin tabs. Each fragment name is the channel identifier.


Patching components

Components included with a custom tag attribute are also fragments and can be re-rendered the same way:

<Example tag="article" value="42" on:interaction />

This renders as and participates in the same dirty-check + SSE push cycle as named fragments.

Components are always server-rendered first. The on: attribute controls when (and whether) the client-side script is instantiated.