Open-Source Wikis

/

Svelte

/

Svelte

/

Architecture

sveltejs/svelte

Architecture

Active contributors: Rich Harris, Simon H, Dominic Gannaway

One-paragraph summary

A Svelte component is processed in two independent target lanes — client and server — that share a single front-end (parse + analyze) and diverge in transform and runtime. The compiler walks the component AST and generates JavaScript that calls into a small set of runtime primitives (mount, hydrate, blocks like each, if, await, and reactive primitives like state, derived, effect). The runtime, in turn, schedules updates through a fine-grained signals system implemented in packages/svelte/src/internal/client/reactivity.

Major subsystems

Area Path Responsibility
Compiler front-end packages/svelte/src/compiler/phases/1-parse .svelte → AST + script/style extraction
Compiler analysis packages/svelte/src/compiler/phases/2-analyze Scope tracking, CSS pruning, validation, runes detection
Client transform packages/svelte/src/compiler/phases/3-transform/client AST → DOM-targeted JS (per-node visitors)
Server transform packages/svelte/src/compiler/phases/3-transform/server AST → HTML-emitting JS
Client runtime packages/svelte/src/internal/client mount/hydrate, blocks, bindings, events, transitions
Server runtime packages/svelte/src/internal/server streaming-friendly HTML renderer
Reactivity primitives packages/svelte/src/internal/client/reactivity Source, Derived, Effect, Batch, props, store
Public reactive types packages/svelte/src/reactivity SvelteMap, SvelteSet, SvelteDate, SvelteURL, etc.
Animation/motion packages/svelte/src/transition, animate, motion, easing Built-in transitions, flip, spring, tweened
Stores (legacy) packages/svelte/src/store Svelte-3 style writable/readable stores
Preprocessor packages/svelte/src/compiler/preprocess Pluggable script/style/markup transforms before compile

Compile-then-run pipeline

graph LR
    SRC[".svelte source"] --> PARSE["parse<br/><code>1-parse/index.js</code>"]
    PARSE --> AST["AST<br/>(fragment + instance + module)"]
    AST --> ANALYZE["analyze_component<br/><code>2-analyze/index.js</code>"]
    ANALYZE --> ANALYSIS["ComponentAnalysis<br/>+ scope graph"]
    ANALYSIS --> TC["transform_component(client)<br/><code>3-transform/client/transform-client.js</code>"]
    ANALYSIS --> TS["transform_component(server)<br/><code>3-transform/server/transform-server.js</code>"]
    TC --> JSC["client JS<br/>(imports svelte/internal/client)"]
    TS --> JSS["server JS<br/>(imports svelte/internal/server)"]
    JSC --> RUNC["client runtime<br/>mount/hydrate"]
    JSS --> RUNS["server runtime<br/>render → HTML"]

The entry point that orchestrates the pipeline is compile() in packages/svelte/src/compiler/index.js. It calls parse, optionally strips TypeScript via remove_typescript_nodes, then analyze_component and transform_component. compileModule follows the same pattern for .svelte.js/.svelte.ts files that contain runes outside a component.

Reactivity at runtime

The runtime is a fine-grained signals system. The three node types are kept in packages/svelte/src/internal/client/reactivity:

graph TD
    Source["Source<br/><code>$state(...)</code>"] -->|read by| Derived["Derived<br/><code>$derived(...)</code>"]
    Source -->|read by| Effect["Effect<br/><code>$effect(...)</code>, blocks, bindings"]
    Derived -->|read by| Effect
    Effect -->|writes| Source
    Effect -->|enqueues into| Batch["Batch<br/>reactivity/batch.js"]
    Batch -->|flushes| Effect
  • Source — leaf reactive value (reactivity/sources.js).
  • Derived — pure computation that re-runs when its sources change (reactivity/deriveds.js).
  • Effect — side-effectful reaction; blocks, attribute updates, transitions all schedule effects (reactivity/effects.js).
  • Batch — coalesces multiple writes into a single flush so the DOM updates once per microtask (reactivity/batch.js).

$state writes are made deeply reactive via JS Proxy (see packages/svelte/src/internal/client/proxy.js), which walks property reads/writes and creates Sources on the fly.

Mount / hydrate

The client runtime renders or attaches a component via three entry points exported from packages/svelte/src/internal/client/render.js: mount, hydrate, unmount. Each one runs the compiled component function inside a freshly-minted ComponentContext (internal/client/context.js) and a root Effect so that subsequent reactive updates have a stable owner.

Server rendering

The server pipeline produces an HTML string plus collected <head> content and CSP nonces. The core is Renderer in packages/svelte/src/internal/server/renderer.js. The compiled server module pushes strings, comments, and child renders onto a tree of Renderer nodes; the top-level render() (exported via packages/svelte/src/server/index.js) collects them. Async-aware rendering is handled by promise-flushing logic in the same file.

Cross-cutting flows

  • Bindings (bind:value, bind:this, etc.) — compiled into bind_* calls from internal/client/dom/elements/bindings/* and create reciprocal effects that read+write a Source.
  • Transitions/animations — compiled <div transition:...> becomes a call to transition() in internal/client/dom/elements/transitions.js, which manages the intro/outro lifecycle and integrates with the reactivity scheduler.
  • Stores — both legacy writable/readable (packages/svelte/src/store) and the new createSubscriber (packages/svelte/src/reactivity/create-subscriber.js) interoperate with effects.

For the deepest dive on each subsystem, see the packages and systems sections.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Architecture – Svelte wiki | Factory