The Runtime System encompasses the reactive execution engine that powers Svelte applications. While the server runtime is a minimal string-generation layer, the client runtime is a sophisticated system managing fine-grained reactivity, DOM updates, and component lifecycle. It coordinates reactive state management, DOM updates, component lifecycle, and effect scheduling.
The runtime system is built around a signal-based reactivity model with three core primitives: Sources (state), Derived (computed values), and Effects (side effects and DOM updates). These are coordinated by a central runtime that manages dependency tracking, batching, and scheduling.
The following diagram bridges the high-level runtime concepts to the specific internal code entities that implement them.
Sources: packages/svelte/src/internal/client/runtime.js73-83 packages/svelte/src/internal/client/reactivity/sources.js76-109 packages/svelte/src/internal/client/reactivity/deriveds.js71-113 packages/svelte/src/internal/client/reactivity/effects.js204-248 packages/svelte/src/internal/client/reactivity/batch.js98-120 packages/svelte/src/internal/client/render.js66-95
The runtime implements a push-pull hybrid reactivity system where signals track their dependencies and notify consumers when values change. Each signal maintains a list of reactions and participates in automatic dependency tracking via active_reaction.
For a deep dive into the signals engine, see Reactivity System.
The runtime automatically tracks dependencies during signal evaluation using global tracking variables. When a signal is read via get(), it registers itself as a dependency of the currently active reaction.
| Global Variable | Role |
|---|---|
active_reaction | The currently executing Reaction (Derived or Effect) used for dependency tracking. packages/svelte/src/internal/client/runtime.js73 |
active_effect | The currently executing Effect, used to manage the effect hierarchy and nesting. packages/svelte/src/internal/client/runtime.js83 |
new_deps | An array of dependencies discovered during the current execution of a reaction. packages/svelte/src/internal/client/runtime.js114 |
write_version | A global counter incremented on every state change to detect signal staleness. packages/svelte/src/internal/client/runtime.js134 |
Sources: packages/svelte/src/internal/client/runtime.js73-148
Updates are not applied immediately but are batched to ensure consistency and performance. The Batch class manages a "fork and commit" lifecycle where changes are captured in a current map before being applied to the main state.
For details on update batching and asynchronous dependencies, see Batch System and Async Handling.
When a source is updated via internal_set, it ensures a Batch exists via Batch.ensure() packages/svelte/src/internal/client/reactivity/sources.js186 The batch captures the value packages/svelte/src/internal/client/reactivity/sources.js187 and schedules a flush of the reactive graph.
Sources: packages/svelte/src/internal/client/reactivity/sources.js182-263 packages/svelte/src/internal/client/reactivity/batch.js98-231
Effects are the mechanism by which the runtime performs side effects, including DOM updates and user-defined logic. They form a tree structure (via parent, first, and next pointers) that mirrors the component hierarchy.
For details on effect hierarchies and error boundaries, see Component Lifecycle.
teardown() or internal renderers, these run synchronously during the render phase to update the DOM. packages/svelte/src/internal/client/reactivity/effects.js194$effect() (internally user_effect()), these are typically deferred until after the component has mounted. packages/svelte/src/internal/client/reactivity/effects.js204effect_root(), these provide a top-level reactive context that can be manually destroyed. packages/svelte/src/internal/client/reactivity/effects.js260Sources: packages/svelte/src/internal/client/reactivity/effects.js71-117 packages/svelte/src/internal/client/reactivity/effects.js193-267
The runtime manages conditional and iterative rendering through specialized block functions. These functions interface with the reactivity system to add, remove, or move DOM branches based on state changes.
For details on reconciliation algorithms and keyed list optimizations, see Control Flow Blocks.
| Block | Runtime Function | Core Logic |
|---|---|---|
{#if} | if_block() | Manages a single branch effect that re-runs when the condition changes. packages/svelte/src/internal/client/dom/blocks/if.js8 |
{#each} | each() | Uses reconcile() to diff collections and manage EachItem instances. packages/svelte/src/internal/client/dom/blocks/each.js177 |
{#await} | await_block() | Interfaces with async_derived and flatten to handle Promise states. packages/svelte/src/internal/client/reactivity/async.js35 |
Sources: packages/svelte/src/internal/client/dom/blocks/each.js177-260 packages/svelte/src/internal/client/reactivity/async.js35-101
Components enter the DOM via mount() or hydrate(). The runtime manages the transition from server-rendered HTML to interactive client-side state using hydration markers.
Sources: packages/svelte/src/internal/client/render.js66-151 packages/svelte/src/internal/client/render.js162-214
mount(): Attaches a component to a target element synchronously packages/svelte/src/internal/client/render.js66hydrate(): Attempts to reuse existing DOM nodes, matching them against hydration markers like HYDRATION_START packages/svelte/src/internal/client/render.js95-120component_root(): Creates the ROOT_EFFECT that governs the entire component tree's lifetime packages/svelte/src/internal/client/render.js172For more details on the mounting process, see Component Lifecycle.