@sigx/ssr-islands · Stable

Islands#

@sigx/ssr-islands adds islands architecture to SignalX SSR: ship a static, server-rendered page and hydrate only the interactive components, each on its own schedule, with optional per-island code splitting.

v0.13.0 ESM-only MIT

It is the first-party reference strategy pack built entirely on the pluggable @sigx/server-renderer plugin API — not baked into core. The base renderer is strategy-agnostic; islands is just an SSRPlugin registered on top (installed automatically as a dependency). The base renderer hydrates the whole tree; islands lets you hydrate just the parts marked with client:* directives — everything else stays as cheap static HTML. Because it ships against the same public hooks, a third party can author their own strategy pack the same way.

It ships from the core monorepo (signalxjs/core, packages/ssr-islands) and is released in lockstep with @sigx/server-renderer.

Why islands#

Most pages are mostly static. Hydrating the entire tree ships and runs JavaScript for content that never changes. With islands you opt in to interactivity per component:

  • A client:visible chart hydrates only when scrolled into view.
  • A client:idle widget waits for the browser to be idle.
  • The surrounding article ships zero client JS.

The three pieces#

Using islands always involves the same trio (from the package's own quick-start):

TSX
// 1. Server — install the pack on your app
import { createSSR } from '@sigx/server-renderer';
import { islandsPlugin } from '@sigx/ssr-islands';
import { defineApp } from 'sigx';

const app = defineApp(<App />).use(islandsPlugin());
const html = await createSSR().render(app);
TypeScript
// 2. Client — register island components, then hydrate them
import { hydrateIslands, registerComponent } from '@sigx/ssr-islands';
import { Counter } from './components/Counter';

registerComponent('Counter', Counter);
hydrateIslands();
TSX
// 3. JSX types — enable the client:* attributes
import '@sigx/ssr-islands/jsx';

<Counter client:visible />
<Widget client:idle />

The server plugin maps each client:* directive onto a core boundary record, captures the component's signal state, and injects the window.__SIGX_BOUNDARIES__ hydration table. On the client, hydrateIslands() reads that table and schedules each island according to its strategy.

Hydration strategies#

DirectiveHydrates…
client:loadimmediately on page load
client:idleduring browser idle time (requestIdleCallback)
client:visiblewhen the element scrolls into view (IntersectionObserver)
client:mediawhen a media query matches (client:media="(min-width: 768px)")
client:onlyskip SSR entirely — empty placeholder on the server, mount fresh on the client

See Client directives for the details of each.

Next steps#