Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,240 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

svelte-rs

The Svelte 5 compiler, rewritten in Rust.

Drop-in replacement for svelte/compiler (pinned to svelte@5.56.4) — same JS output, ~9× faster.

CodSpeed npm vite-plugin tests

Playground · Issues

⚠️ WIP / canary. Built by a human with heavy AI assistance. Expect bugs, missing edge cases, and breaking changes. Not production-ready — please report what breaks.


Why

svelte-rs compiler benchmark — ~9× faster than svelte/compiler, ~3.7× faster than rsvelte
  • Byte-exact JS output~3,000 cases (1,840 cluster + 1,182 legacy), each diffed against the reference compiler in all four modes (client/server × dev/prod) — 12,000+ passing comparisons.
  • Diagnostics parity823 cases across 27 categories (a11y, runes, CSS, TypeScript, …), matched against svelte/compiler's own warnings and errors by code, severity, and span.
  • Drop-in — same compile() / compileModule() API as svelte/compiler.
  • ~9× faster on two anonymized real-world production codebases (8.6–10.2× across every mode, 3.7–4.9× over rsvelte's native binding).
  • Ready to try — wired into a fork of vite-plugin-svelte, so it runs in a real Vite app today.

Install

As a compiler

npm i -D @mrwaip/svelte-rs
import { compile } from '@mrwaip/svelte-rs/compiler';

const { js } = compile(
  `<script>let { name } = $props();</script><h1>hello {name}</h1>`,
  { filename: 'Hello.svelte', generate: 'client' }
);

console.log(js.code);

The API mirrors svelte/compiler; see packages/svelte-rs/compiler/index.d.ts. A few opt-in extras beyond the reference API:

  • warningFilter: (warning) => boolean — matches Svelte 5's option; drops warnings the predicate rejects.
  • suppress: WarningCode[] — a typed list of warning codes dropped at the source. Cheaper than filtering after the fact: suppressed warnings are never built, framed, or serialized.
  • transformTypescript: true — transpiles TypeScript features that emit runtime code (enum, namespace, parameter properties, decorators) instead of reporting typescript_invalid_feature. Behaviourally equivalent to vitePreprocess({ script: true }), not byte-equal: esbuild inlines enum member reads and renames shadowed parameters, we don't.
  • transformStyle: true (+ loadPaths) — compiles lang="scss" / lang="sass" with grass before the CSS pipeline. Semantically equal to dart-sass on our corpus (verified by lightningcss re-minification), but grass does not promise full dart-sass compatibility — keep a JS preprocessor fallback for unsupported constructs.
  • cssTargets: string[] — browserslist queries; lowers modern CSS and adds vendor prefixes via lightningcss, replacing postcss + autoprefixer. Not byte-equal to autoprefixer: the prefix databases disagree (e.g. autoprefixer still emits -moz-user-select where lightningcss does not).
  • withDiagnostics: true — returns { js, css, diagnostics } where each diagnostic carries severity: 'error' | 'warning', and never throws on error. Handy for editors, linters, and batch tooling.

Real input → output for every mode lives in tasks/compiler_tests/cluster_cases/: each leaf has case.svelte plus our output and the reference (case-rust.js / case-svelte.js, .dev.js, .server.js, .server.dev.js). The older flat cases2/ suite is legacy but still checked.

In a Vite app

The fork of vite-plugin-svelte routes compile / compileModule through @mrwaip/svelte-rs automatically, falling back to svelte/compiler for options the Rust side doesn't support yet.

npm i -D @mrwaip/vite-plugin-svelte
import { defineConfig } from 'vite';
import { svelte } from '@mrwaip/vite-plugin-svelte';

export default defineConfig({
  plugins: [svelte()],
});

Source: https://github.com/MrWaip/vite-plugin-svelte.

Requirements

Node ^20.19 || ^22.12 || >=24
Platforms Prebuilt binaries for macOS (arm64/x64), Linux glibc & musl/Alpine (x64/arm64), Windows (x64/arm64).
Peer svelte@5.56.4 — Vite plugin falls back to svelte/compiler for unsupported options.

Status

Parity target: svelte@5.56.4. Check this before logging an issue.

Feature matrix & known limitations
Feature Status Notes
Svelte 5 syntax done Runes, template, bindings, directives, events, special elements, diagnostics, a11y.
Svelte 4 legacy done export let, $:, beforeUpdate/afterUpdate, <slot>, <svelte:self>, <svelte:component>, auto-mode detection.
CSS pipeline done analyze + transform + codegen.
TypeScript done Script stripping only — no type checking.
.svelte.js / .svelte.ts modules done
Dev mode (dev: true) done Byte-exact client-dev and server-dev; some ownership/hydration diagnostics land case-by-case.
SSR (generate: 'server') done Server transform + codegen (prod & dev).
Source maps done js.map / css.map emitted; sourcemap option honored.
HMR done Hot-module-replacement output supported.
Custom elements in progress Basic path works; some option combinations not covered.
Compiler options in progress Most common options honored (incl. discloseVersion, warningFilter); long tail still landing.
Preprocessors done preprocess() with markup / script / style hooks, dependency collection, sourcemap splicing.
Built-in preprocessing opt-in transformTypescript (enum / namespace / decorators via OXC), transformStyle (scss / sass via grass, loadPaths), cssTargets (vendor prefixes via lightningcss). Runs inside the compiler with no Node round trip. Outside the parity contract — see below.

done — no known deficits; OK to log bugs. in progress — partially working; log panics only. not ready — don't file bugs yet.

Known limitations

  • ast option throws; the returned ast is always null.
  • outputFilename option throws.
  • modernAst: true is accepted but ignored (emits unsupported_option_ignored warning).
  • dev: true runtime checks land case-by-case — not all ownership / hydration diagnostics are emitted yet.

Benchmarks

Whole-corpus throughput on two anonymized real-world production codebases — every .svelte file compiled in every mode, single-threaded, one file at a time. Median of 5 runs, measured 2026-07-27 via just bench-compare <dir> on Apple Silicon (macOS arm64), against svelte@5.56.4, @rsvelte/vite-plugin-svelte-native 0.3.1 (native binding) and @rsvelte/compiler 0.9.4 (WASM).

project mode svelte ours rsv-native rsv-wasm vs svelte vs rsv-native vs rsv-wasm
A — 7,910 files, 12.0 MB client 1995.2 ms 221.7 ms 820.2 ms 1334.3 ms 9.00× 3.70× 6.02×
client-dev 2039.3 ms 237.2 ms 877.7 ms n/a 8.60× 3.70× n/a
ssr 1741.1 ms 182.9 ms 683.8 ms 1020.2 ms 9.52× 3.74× 5.58×
ssr-dev 1914.8 ms 201.2 ms 749.7 ms n/a 9.51× 3.73× n/a
B — 10,093 files, 14.4 MB client 2831.3 ms 313.3 ms 1507.7 ms 2395.2 ms 9.04× 4.81× 7.64×
client-dev 3050.4 ms 335.8 ms 1628.4 ms n/a 9.08× 4.85× n/a
ssr 2677.5 ms 263.3 ms 1068.4 ms 1603.5 ms 10.17× 4.06× 6.09×
ssr-dev 2810.1 ms 283.5 ms 1144.4 ms n/a 9.91× 4.04× n/a

Both projects are closed-source, so these runs are not reproducible from this repository — just bench-compare against the repo's own fixture corpus is. An explicit directory is scanned as-is, so the file counts include whatever .svelte files the checkout carries, vendored dependencies included.

On project A all four compilers compiled the identical file set (zero skips). On project B rsvelte rejects one file the other three accept (svelte 24 / ours 24 / rsvelte 25 skipped), so its columns there are measured on a set smaller by one file.

Reproduce with just bench-compare. Per-run instruction-count benchmarks (64 total) also run on every commit via CodSpeed. The rsvelte columns appear when its packages are installed. These are rsvelte's serial compile numbers, matching our single-file harness — its parallel compileBatch (rayon) is not measured here.

Alternatives

  • rsvelte — another Rust port of the Svelte 5 compiler, also built on OXC. Ships a WASM build (@rsvelte/compiler), a native NAPI binding, and a multi-threaded compileBatch API.

Try it locally

Requires Rust, Node, and just (cargo install just or brew install just).

just playground               # build wasm + serve playground
just quick-check App.svelte   # diff one component against svelte/compiler
just test-compiler            # run the 12,000+ comparison e2e suite (all modes)
just test-diagnostics         # run the 823-case diagnostics parity suite

Contributing

Standard PRs welcome — no AI required. Day-to-day work uses Claude Code with repo-specific skills under .claude/skills/. Before opening a PR: just test-compiler && just test-diagnostics && just lint must be green.

Bugs and questions: https://github.com/MrWaip/svelte-rs/issues.

Acknowledgements

  • Svelte — the compiler this project mirrors; reference output is the source of truth.
  • OXC — JS parser, AST, and codegen.
  • vite-plugin-svelte — base of the Vite integration fork.

License

MIT © Lobkov Constantine

About

Rust Svelte Compiler

Topics

Resources

Stars

20 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages