@sigil-dev/runtime
v0.9.2
Published
Runtime for the Sigil framework
Downloads
5,579
Readme
@sigil-dev/runtime
Signals-based reactivity for the DOM using direct mutations.
bun add @sigil-dev/runtimeWhat it is
A small reactive primitive library. Signals track dependencies automatically — when a value changes, only the effects that read it re-run.
Objects and arrays use Proxy for deep reactivity without any special syntax.
Inspired by Solid's reactive model.
Primitives
createSignal
import { createSignal } from "@sigil-dev/runtime";
const count = createSignal(0);
count() // read — 0
count.set(5) // write
count.peek() // read without trackingObjects and arrays are deeply reactive via Proxy and you mutate them directly:
const user = createSignal({ name: "Rei", score: 0 });
user().score++ // triggers effects that read score
user().name = "Asuka" // triggers effects that read name
user.set({ name: "Misato", score: 100 }) // replace entire objectcreateEffect
Runs immediately, re-runs when any signal it read changes. Returns a dispose function.
import { createEffect } from "@sigil-dev/runtime";
const dispose = createEffect(() => {
document.title = `Score: ${user().score}`;
return () => console.log("cleanup before rerun");
});
dispose(); // stop trackingDependencies are tracked automatically. If a signal is conditionally read, the dependency is updated on each run — no stale subscriptions.
createMemo
A derived signal. Cached until its dependencies change.
import { createMemo } from "@sigil-dev/runtime";
const fullName = createMemo(() => `${first()} ${last()}`);
fullName() // read like any other signalbatch
Defer effect notifications until a block completes. Useful for multiple related writes.
import { batch } from "@sigil-dev/runtime";
batch(() => {
x.set(1);
y.set(2);
// effects fire once, not twice
});withEffectScope
Group effects so they can all be torn down at once. Essential for component lifecycle.
import { withEffectScope } from "@sigil-dev/runtime";
const dispose = withEffectScope(() => {
createEffect(() => console.log(x()));
createEffect(() => console.log(y()));
});
dispose(); // kills bothScopes nest correctly. Inner dispose does not affect outer scope.
Context
import { createContext, setContext, getContext } from "@sigil-dev/runtime";
const ThemeKey = createContext<"light" | "dark">();
setContext(ThemeKey, "dark");
getContext(ThemeKey); // "dark"Hydration utilities
NOTE: You probably dont want to use this manually.
claim, claimText, claimComment, reconcile, hydrateKeyedList are used by the Sigil compiler for SSR hydration. Claim existing server-rendered DOM nodes instead of creating new ones.
import { claim, claimText, reconcile } from "@sigil-dev/runtime";
// claim an existing <div> from an SSR pool instead of createElement
const el = claim(nodes, "div", parent);Design
No virtual DOM. Effects write directly to DOM nodes. The update path is:
signal.set(newValue)
→ notify subscribers
→ effect re-runs
→ direct DOM mutationIf a signal changes, the effects that depend on it run synchronously (or are batched if inside batch()).
Deep reactivity on objects uses Proxy rather than explicit getter/setter pairs. This means you can pass a signal's value to any code that expects a plain object and mutations will still be tracked.
Used by
@sigil-dev/compiler compiles $state, $derived, and $effect macros down to these primitives at build time. You can use this library directly if you want explicit control or are building outside the Sigil compiler pipeline.
