rsvelte: AI 時代の Svelte ツールチェーンを Rust で作り直す
私が働いている Flyle では、複数の AI エージェントを並列で走らせて開発することが当たり前になっている。この開発スタイルでは、エージェントが実装のたびに型検査や Lint を回すため、静的検査の実行回数が人間だけで開発していた頃とは比較にならないほど増える。検査が並列で走れば CPU とメモリを使い切り、1 回あたりの検査時間はさらに伸びる。エージェントは検査が終わるまで次の修正に進めないので、静的検査の所要時間が、そのまま 1 ループの所要時間の下限になる。
そして Svelte プロジェクトでは、この静的検査が特に遅い。この問題を解決するために、私は rsvelte という、Svelte のツールチェーンを Rust で作り直すプロジェクトを開発している。この記事では、なぜ今それが必要なのか、rsvelte が何をするものなのかを整理する。
tl;dr
- AI エージェントはループ毎に静的検査を回すため、検査の所要時間が 1 ループの所要時間の下限になり、CPU/メモリ消費も並列数を制約する
- Rust / ネイティブベースのツールは静的検査を桁で高速化しつつあるが、
.svelteの Svelte 固有処理(パース・変換・Lint・フォーマット)には JavaScript 実装が残っている - rsvelte は Svelte ツールチェーンのドロップイン代替を目標とする Rust 実装群である。言語仕様への独自拡張は加えない。early stage で、到達度はパッケージごとに異なる
- Flyle の本番フロントエンド(公式構成で 8,795 ファイルを検査)の型検査は、rsvelte-check への置き換えだけで 51.4s → 30.6s(1.7 倍、CPU 約 56% 減)、検査エンジンの tsgo 化を合わせて 9.0s(5.7 倍)
- 実行ルール集合を揃えた Svelte 固有 Lint は約 20 倍(診断 382 件は両実装で完全一致)。8 並列の高負荷条件では両構成に共通する TypeScript 処理がボトルネックになり型検査の差は縮む。価値は個々の検査を速く終わらせて重複区間を減らす点にあると考えている
1. なぜ今、静的検査の「速度」なのか
1.1 実装者が AI になり、品質保証はハーネスに移った
AI エージェントが実装の主体になると、品質を支える仕組みの重心が変わる。人間中心の開発でも静的検査は重要だったが、エージェントが書く時代には、エージェントの出力を機械的に検証するハーネスが品質の主な担い手になる。
ハーネスにはいくつかのレイヤーがある。仕様や設計をドキュメントや型で表現しエージェントの前提を固定する設計ハーネス、実装のたびに出力を検証する開発ハーネス、振る舞いを検証するテストハーネスなどだ。それぞれに論じる価値があるが、この記事では開発ハーネスの中核である静的検査基盤(フォーマッター、型検査、Linter、未使用コード検出)に絞る。
1.2 静的検査の実行モデルが変わった
静的検査そのものは昔からある。変わったのは実行モデルだ。
人間中心の開発でも静的検査は重要だった。ただし、一人の開発者が短時間に何度もフル検査を起動し、さらに複数の作業ツリーで同じ検査を並列実行することは、現在のエージェント開発ほど一般的ではなかった。
エージェントは違う。Codex CLI のように Language Server を利用しないエージェントもあり、Claude Code のように利用できる場合でも、並列インスタンスが Language Server を共有するとは限らない。各インスタンスが独立した Language Server を起動すれば、その解析処理とメモリ消費は並列数に応じて重複する。さらに、LSP の診断範囲や設定が CI と一致するとは限らないため、多くの環境では最終的な品質ゲートとして CI と同じ CLI 検査も必要になる。1 つのタスクの中で何度も回すし、複数のエージェントを並列で走らせれば、その数だけ検査も並列に走る。つまり静的検査は、比較的低頻度・低並列で実行するものから、高頻度・高並列で実行するものに変わった。
正確に言えば、これは AI に固有の問題ではない。CI や pre-commit のように CLI からフル検査を回す仕組みは以前からあり、フル検査の遅さも昔からの既知の問題だった。変わったのは実行の頻度と並列度である。静的検査がボトルネックになるワークロードは以前から少しずつ増えていたが、AI エージェントによる並列開発は、その問題を最も極端な形で表面化させた。この記事が AI を軸に論じるのはそのためで、以降の議論は CLI でフル検査を大量に実行するワークロード全般に当てはまる。
1.3 遅さのコストは 2 つの形で現れる
このとき、検査の遅さはレイテンシとリソース消費という 2 つの側面でコストになる(両者は相互に影響する)。
1 つ目はレイテンシである。検査結果を同期的に待って次の修正方針を決めるループでは、検査時間がそのままクリティカルパスになる。検査に 5 分かかるなら、1 ループは最短でも 5 分だ。私の経験でも、検査一式に数分かかるプロジェクトは珍しくない。本記事で実測する Flyle の本番フロントエンドでも、型検査単体で約 51 秒かかる(3.3)。1 タスクで 5 回検査を回せば、待ち時間はその 5 倍になる。
2 つ目はリソースである。現行の Svelte 検査構成は、TypeScript 検査エンジンや変換処理を含むプロセスツリー全体として大きな CPU・メモリを使用する。後述の実測(3.3)では、Flyle の本番フロントエンドの型検査で、現行の JS 構成はプロセスツリー全体で peak 4.2GB のメモリと約 105 CPU 秒を消費した。これが並列で走るとローカルマシンのリソースを使い切ってしまう。つまり検査のリソース消費が、同時に動かせるエージェント数の主要な制約の 1 つになる。
1.4 「CI でやればいい」「マシンを強くすればいい」だけではダメな理由
CI に検査を寄せる案は、フィードバックのタイミングを後ろにずらすだけだ。エージェントは検査結果を次の修正に利用するため、ループ内の早いフィードバックが重要になる。検査を回さずに実装を進めれば、誤った前提の上に次の実装が積み上がり、エラーを後からまとめて検出したときの修正コストは膨らむ。次の実装の判断に使うには、検査はループの中で走る必要がある。
マシンの増強も有効ではある。ただし検査プロセスの消費量が変わらなければ、並列数に応じて必要なコア数とメモリも増える。ツール側の効率改善は、同じハードウェアで扱える並列度そのものを高める。
2. Rust ベースのツールチェーンと Svelte の現状
2.1 静的検査ツールを桁違いに高速化する動き
この問題への回答として、静的検査ツールを Rust やネイティブコードで書き直す動きがすでに進んでいる。
- oxc プロジェクトの oxlint は、ESLint の 50〜100 倍(公称)の速度で Lint を実行する
- tsgo(TypeScript コンパイラの Go 移植)は、tsc 比で約 10 倍の高速化を公称している(A 10x Faster TypeScript)
- Biome は Rust 製のフォーマッター・リンターとして同様の高速化を実現している
なお、この高速化は「Rust で書けば速くなる」という単純な話ではない。言語の実行効率に加えて、並列処理を前提とした設計、再パースの削減、メモリ効率の良いデータ構造など、実装全体の設計で達成した速度である。
重要なのは、速度が桁で変わると振る舞いも変わることだ。10 分かかる検査は並列エージェントの間で重なり合い、リソースを奪い合う。数秒で終わる検査は、そもそも検査同士が同時に走っている時間帯が短いので、リソース競合自体が起きにくい。レイテンシの改善がリソース問題も同時に緩和する。
2.2 しかし Svelte 固有の処理には JavaScript 実装が残っている
ところが、Svelte 固有の処理はこの流れに十分に乗れていない。
- Lint: oxlint は alpha 段階の仕組みで
.svelte内の script 部分を抽出して検査できるようになったが、テンプレートや style を含む Svelte 固有のセマンティクスを検査する基盤はまだない。Svelte 固有ルールは JavaScript 製の eslint-plugin-svelte + ESLint に依存したままである - フォーマット: oxfmt の Svelte 対応は、Svelte の構造部分を JavaScript 製の prettier-plugin-svelte に依存し、埋め込み JS/TS のみを oxc_formatter に委譲する構成である(埋め込み CSS は Prettier 組み込みのフォーマッタで処理する)。そのため
.svelteの構造と埋め込み CSS のパースと整形は依然として Prettier 側のコストを受ける - 型検査: svelte-check は svelte2tsx で
.svelteを TypeScript に変換して検査エンジンに渡す構成である。検査エンジンは--tsgoで高速化できるようになったが、変換とオーケストレーションは JavaScript の速度で動く
つまり、公式ツールでも TypeScript 検査部分は tsgo によって高速化できるようになった一方で、Svelte のパース、svelte2tsx 変換、テンプレートの Lint、フォーマットといった Svelte 固有の処理には、依然として JavaScript 実装が残っている。この構造は Svelte 固有のものではなく、Vue のような独自のテンプレート言語を持つフレームワークも同型の問題を抱えている。
3. rsvelte
rsvelte は、このギャップを埋めるためのプロジェクトである。
3.1 目標: Svelte ツールチェーンのドロップイン代替
rsvelte の長期目標は、Svelte の既存ツールチェーンのドロップイン代替になることだ。設定ファイルもコマンドの使い方も変えずに、実装だけが Rust に置き換わる状態を目指している。そして、Svelte の言語仕様やコンパイラの意味論に独自拡張を加えないことを設計原則にしている(CLI フラグやキャッシュのような、ツールとしての付加機能はある)。
理由は、最終的に切り替えコストと撤退コストを限りなく小さくするためだ。独自機能を持つ代替ツールは、採用した時点でその機能への依存が生まれ、元のツールに戻る選択肢が失われていく。互換性が保たれていれば、導入して効果を測り、問題があれば戻す、という試行が安全にできる。oxlint が ESLint ルールの忠実な移植によって信頼を得たのと同じ戦略である。そしてこの互換性は、後述する「Svelte 組織での公式メンテナンス」を目指す上での前提条件でもある。
互換性は宣言ではなく検証で担保する方針を取っている。コンパイラは、Svelte v5.56.4 公式テストスイートのうち rsvelte が対象とする 3,500 以上のフィクスチャで 100% 合格している(Svelte 4→5 マイグレーターや一部の個別フィクスチャは対象外)。加えて、実世界の約 30 リポジトリ・約 12,000 コンパイル単位のコードを公式コンパイラと rsvelte の両方でコンパイルして出力を比較し続けており、既知の構造的差分は client 8 件・server 0 件である(いずれも commit 76ac14b3 時点。リンク先の README やダッシュボードは更新タイミングにより数値が異なる場合がある)。CI はこの既知差分リストを「増やすことを禁止する」ラチェットとして運用しており、差分ごとに原因を文書化している。
ただし、ドロップインへの到達度はパッケージごとに大きく異なる。フィクスチャ 100% は公開 API の完全互換を意味しない。CSS ハッシュ関数など関数値オプションの制約が残るほか、各パッケージの現状は 3.2 の表に示す通りで、正確に言えば現状は「完成したドロップイン代替」ではなく「ドロップイン代替を目標に、互換性を検証しながら近づけている複数の互換実装」である。
3.2 コンポーネント
rsvelte は静的検査基盤を構成する各ツールを個別のパッケージとして提供している。成熟度が大きく異なるため、内容と現状を併記する。
| 領域 | パッケージ | 内容 | 現状 |
|---|---|---|---|
| コンパイラ | @rsvelte/compiler |
Svelte 5 コンパイラの Rust 移植 | 対象フィクスチャ 100% 合格。実コード出力の既知構造差 client 8 / server 0 |
| ビルド | @rsvelte/vite-plugin-svelte |
公式 vite-plugin-svelte の fork(API 同一) | experimental |
| 型検査(変換) | @rsvelte/svelte2tsx |
svelte2tsx の Rust 移植 | 出力の既知差分 0。ただし API は非同期(WASM 初期化のため)で上流と異なる |
| 型検査(CLI) | @rsvelte/svelte-check |
svelte-check の移植。検査エンジンとして tsc / tsgo を選択できる | early stage。一部 CLI フラグに差分。公式版の併用なしの CI ゲート利用はまだ非推奨 |
| フォーマット | @rsvelte/fmt |
prettier-plugin-svelte の移植。oxfmt と連携 | 実コードでの出力既知差分 40 件。設定は .oxfmtrc ベース(Prettier 設定は読まない) |
| Lint | @rsvelte/lint |
eslint-plugin-svelte の 80 ルールを移植 | 現時点では ESLint の代替ではなく補完という位置づけ |
| エディタ | @rsvelte/language-server / rsvelte-vscode |
Language Server と VS Code 拡張(別パッケージ) | フォーマットと Lint のみ。型検査・補完・定義ジャンプは対象外 |
ツールを横並びで作っているのは目的ではなく帰結である。フォーマッター・型検査・Lint はいずれも Svelte パーサーに依存しているが、ネイティブツールから JavaScript 製の Svelte コンパイラを利用するには JS ランタイムやプロセス境界を越える必要があり、oxc の AST・semantic パイプラインへ直接統合することはできない。1 つの Rust パーサー(oxc ベース)を全ツールで共有することが、後述する oxc 統合の前提になる。
型検査については補足が要る。公式の svelte-check にも --tsgo オプションが既にあり、TS 検査エンジン自体は両者が共有できる。rsvelte の差分は svelte2tsx 変換とオーケストレーションの Rust 化であり、次のベンチマークでは TypeScript 実装を揃えた比較も行い、Svelte 側の実装差をできるだけ分離する。
3.3 ベンチマーク
この記事のために手元で実測した。数字を読む前に、測定の性質を 2 つに分けておく。エンジン処理(ファイルをメモリに読み込んだ状態での、変換・整形処理そのもののスループット)と、エンドツーエンド(CLI 起動からプロセス終了までの、ユーザーが体験する時間)である。前者の倍率は後者をそのまま意味しない。
主な条件: Apple M4 Pro(12 コア)/ 48GB、Node.js 24.13.1、rsvelte commit 76ac14b3(ソースからビルド)、Svelte v5.56.4、svelte-check 4.7.3、typescript 5.9.3、tsgo 7.0.0-dev.20260707.2、eslint 10.7.0、eslint-plugin-svelte 3.21.0。いずれも同一マシン・同一コーパスで複数回実行の中央値を採る。計測スクリプトと生データは rsvelte リポジトリの scripts/bench/ にある(エンジン処理の公開値とグラフは benchmark ページ)。
計測手法の詳細
- CPU 時間は
/usr/bin/time -l(user + sys、待機した子プロセスを含む)。RSS はpsでプロセスツリーを 100ms 間隔で合算した概算値で、共有ページを重複計上し得る。チェッカー本体と TS エンジンの分離は PID の親子関係に基づく、プロセス構造ベースの概算である - flowbite の計測は、検査ツールがワークスペースに書き込むオーバーレイ成果物が次の実行に影響するため、実行ごとに APFS clonefile で新品のワークスペースを用意した、ツールキャッシュなし・非インクリメンタル実行(OS のページキャッシュ等は制御していない)
- flowbite ワークロードは両実装とも約 900 件のエラーを報告する(js 885 / rs 926、ファイルとメッセージ単位の一致 669 件)。セットアップ(
pnpm install --ignore-scripts+ typescript / @typescript/native-preview の追加 +svelte-kit sync)がライブラリ開発用の完全な環境を再現していないためで、正常な CI 結果ではなく性能傾向を確認する参考値である - Flyle の計測は実行ごとに
svelte-kit syncとオーバーレイ削除で状態をリセットし、1 回のウォームアップ後 5 回の中央値を採った - Lint の設定: ESLint 側は eslint-plugin-svelte(flat/recommended)+ TS パーサーを
srcの全 1,296 ファイルに適用し、svelte/* 以外のルールと未使用ディレクティブ報告は無効化。rsvelte-lint 側は ESLint の解決済み設定から svelte/* ルール 37 個を同一重大度でインポートした設定(extends: ["none"]ベース)で実行 - 37 ルールのうち
svelte/no-unused-propsだけは比較から除外した。ESLint 実装は TypeScript の型情報を必要とし、この環境では何も検出しない一方、rsvelte-lint は型情報なしで 11 件検出するため、両側の仕事量と出力を揃える目的で rsvelte 側で無効化した
3.3.1 型検査エンドツーエンド(Flyle 本番)
まず、ユーザー(あるいはエージェント)が実際に体験するエンドツーエンドから見る。私が働いている Flyle の本番フロントエンド(SvelteKit アプリ。公式 svelte-check では 8,795 ファイルが検査対象になる)で計測した。効果は 2 段に分解できる。
svelte-check + TypeScript LS 51.4s ← 現行 CI 構成
↓ rsvelte 化(TypeScript は JS 版 5.9.3 のまま)
rsvelte-check + tsc 30.6s (1.7 倍。CPU 104.9s → 45.9s、約 56% 減)
↓ 検査エンジンを tsgo 化
rsvelte-check + tsgo 9.0s (合成で 5.7 倍。CPU 32.1s)
| 構成 | wall time(範囲) | CPU 時間 | peak RSS 総計 | うちチェッカー本体 |
|---|---|---|---|---|
| svelte-check + TypeScript Language Service(現行 CI 構成) | 51.4s(46.9〜64.4) | 104.9s | 4.2GB | 分離不能(LS 一体型) |
| rsvelte-check + tsc | 30.6s(29.8〜36.2) | 45.9s | 3.8GB | 0.12GB |
| rsvelte-check + tsgo | 9.0s(8.6〜9.9) | 32.1s | 5.5GB | 0.12GB |
つまり rsvelte-check への置き換えだけで 1.7 倍(この置き換えには Svelte 側の Rust 化に加えて、Language Service から tsc CLI への実行経路の変更も含まれる)、tsgo 化を合わせて 5.7 倍である。検査結果は js / rs とも 0 errors、警告 44 / 41 件で、差の 3 件はワークスペース境界の 1 ファイルを公式版だけが検査対象に含めたことによる(rs 側は検査ファイル数を機械可読出力に出さないため、対象数の完全な突合はできていない)。メモリは、rsvelte-check 本体の peak がどちらのエンジン構成でも約 0.12GB で、rsvelte 構成ではメモリの大半を TS エンジンが占める(tsgo 構成の合計 5.5GB の大半は tsgo プロセスの消費。同じ JavaScript 版 TypeScript を使う構成同士なら合計も 4.2GB → 3.8GB に減る)。なお公式 svelte-check の --tsgo はこのリポジトリでは検査対象が 355 ファイルに縮み 1,581 件の誤エラーを報告したため、正しく動作しておらず比較から除外した(svelte-check 4.7.3 で確認)。
3.3.2 tsgo を揃えた比較(flowbite-svelte)
Flyle で測れない比較が 2 つある。tsgo 同士の比較(公式 --tsgo が誤動作するため)と、並列実行(独立したワークスペースの複製が N 個必要で、17GB の本番モノレポでは非現実的なため)である。この 2 つは、公式 --tsgo が動作する flowbite-svelte(commit 85f20a0、実 .svelte 1,296 ファイル)で行った。重要な制約を 1 つ明記しておく: このセットアップは flowbite の完全な開発環境を再現していないため、両実装ともモジュール解決起因の診断を約 900 件報告する。したがってこの数値は正しさの突合ではなく、性能傾向を確認する参考値である(詳細は上の「計測手法の詳細」)。tsgo を両方に使い、交互に実行する 10 ペア(ペアごとに実行順を入れ替え、毎回新品のワークスペースを使用)で測った結果は、js 中央値 3.96s(3.84〜4.16)、rs 中央値 2.12s(2.03〜2.36)、ペア内比率の中央値 1.9 倍(1.72〜1.96)だった。エンジン処理の倍率よりずっと小さいのは、エンドツーエンドでは両構成に共通する TypeScript 検査が wall time の大半を占めるためである。
3.3.3 並列実行
次に、この記事の主張に最も直接関わる測定として、同じマシンで N 個の検査プロセスを同時に走らせた(flowbite-svelte、tsgo 構成同士。svelte-check + Language Service 構成は並列時の実行間分散が大きく安定した値を得られなかったため除外)。表の値は「N 件すべてが完了するまでのバッチ完了時間 / 合計 CPU 時間 / 合計 peak RSS」である。
| 同時実行数 | svelte-check + tsgo | rsvelte-check + tsgo |
|---|---|---|
| 1 | 4.0s / 8.1s / 1.3GB | 2.1s / 6.0s / 1.2GB |
| 2 | 4.7s / 17.3s / 2.4GB | 3.5s / 13.1s / 2.2GB |
| 4 | 8.1s / 39.7s / 4.2GB | 6.7s / 28.6s / 4.3GB |
| 8 | 14.1s / 86.0s / 6.9GB | 13.5s / 67.8s / 6.7GB |
N=1 で 1.9 倍あった差は並列度を上げるほど縮み、8 件を同時起動した条件ではほぼ消える(14.1s vs 13.5s)。この結果は、同時起動により検査が重なり続ける高負荷条件では、両構成に共通する tsgo 処理がボトルネックになることを示唆する(それでも合計 CPU 時間を 8 件で割った 1 検査あたりの CPU 消費は 10.8 → 8.5 CPU 秒で約 21% 少なく、合計 RSS は同水準。rayon スレッド数を 12/N に制限する構成も測ったが有意差はなかった)。一方、実運用では検査の開始時刻はずれるため、単独実行時間の短縮が重複区間そのものを減らすと考えている。ただしこれは今回の同時起動ベンチマークでは直接測っておらず、実際のエージェント実行ログでの検証は今後の課題である。
3.3.4 Svelte 固有 Lint
Lint も同じ交互実行の方法で測った(設定は「計測手法の詳細」参照)。これは ESLint 構成全体の置き換えではなく、flat/recommended の Svelte 固有ルールを同一重大度で揃え、それ以外のルールは両側とも無効化した比較である。1 つだけ例外がある。svelte/no-unused-props は ESLint 実装が型情報を必要としこの環境では何も検出しないが、rsvelte-lint は型情報なしで 11 件検出する。両側の仕事量と出力を揃えるため、このルールは rsvelte 側で無効化して比較から外した(詳細は「計測手法の詳細」)。その結果、診断は両実装とも 382 件で完全に一致した。
| wall time | CPU 時間 | peak RSS | |
|---|---|---|---|
| ESLint + eslint-plugin-svelte | 5.02s | 8.4s | 0.86GB |
| rsvelte-lint | 0.25s | 1.7s | 0.05GB |
交互実行 10 ペアの比率中央値は 19.4 倍(範囲 18.0〜23.5)だった。型検査と違って、この比較にはエンドツーエンドの時間を支配する大きな共通 TypeScript フェーズがないため、2 桁の差がそのまま残る。メモリも 0.86GB → 0.05GB と大きく減る。
3.3.5 エンジン単体の性能
最後に、なぜここまで速くなるのかの裏付けとして、エンジン単体のスループットを示す(Svelte 公式テストスイート由来の実 .svelte 3,857 件、事前にメモリへ読み込み済み。3 回のウォームアップ後 10 回実行の中央値):
| 処理 | JS | rsvelte(1 スレッド) | rsvelte(マルチ) | 倍率(マルチ) |
|---|---|---|---|---|
| パース | 149.3ms | 9.0ms | 1.9ms | 79.1× |
| コンパイル(client) | 625.9ms | 202.8ms | 32.9ms | 19.0× |
| コンパイル(SSR) | 510.4ms | 114.1ms | 16.9ms | 30.2× |
| svelte2tsx | 231.6ms | 91.2ms | 11.4ms | 20.4× |
| フォーマット | 2891.6ms | 117.0ms | 23.7ms | 122.2× |
| svelte-check(ツール自身の処理) | 875.2ms | 41.6ms | 15.6ms | 56.2× |
この表の注意点を 3 つ。第一に、svelte-check の行は、両実装とも TypeScript 検査と TSX オーバーレイ生成を無効化し、ファイル走査と Svelte 側のパース・解析・診断生成のみを比較している。第二に、この表は API 呼び出しの計測であり、CLI 起動・ファイル探索・設定解決は含まない。つまり「フォーマットエンジンのスループットが 12 コアで約 120 倍」であって、「format コマンドの体験が 120 倍速くなる」ではない。第三に、コーパスは意図的にコンパイルエラーになるフィクスチャも含んでおり(スクリプトは JS 側の例外を捕捉して無視する)、両実装の成功・失敗件数が完全に一致することまでは検証していない。
ここから 1.3 で挙げた 2 つのコストへの回答が得られる。レイテンシ: 本番リポジトリの型検査 1 回は rsvelte 化だけで 1.7 倍、tsgo 化を合わせて 5.7 倍(51.4s → 9.0s)縮み、Svelte 固有 Lint は約 20 倍縮む。リソース: 型検査の CPU 時間は rsvelte 化だけで約 56% 減(104.9s → 45.9s)、tsgo 化を合わせて 104.9s → 32.1s になる。rsvelte-check 本体のメモリは約 0.12GB(Lint は 0.05GB)と小さく、rsvelte 構成ではメモリの大半を TypeScript エンジンが占める。tsgo を選ぶとエンジン分のメモリは増える。
4. 今日から試す
rsvelte は現在 1.0 前の early stage であり、API は予告なく変わる可能性がある。既知の制約と各パッケージの成熟度は 3.2 の表に示した通りである。その前提で、各ツールは個別に導入できる。導入手順は rsvelte の README を参照してほしい。
ドロップイン代替を目標としているため、既存ツールと併走させて出力を比較する、という試し方ができる。まずはソースを書き換えない型検査を公式版と併走させるのがおすすめだ。フォーマッターには既知の出力差があるため、--check での比較や隔離ブランチから始めると安全である。
5. 今後の方向性
oxc とのネイティブ統合。 oxc 側には外部の言語プラグインを受け入れる実装計画(oxc-project/oxc#21936)があり、Svelte も対象に含まれている。ただし実装はまだ初期段階で、統合時期は未定である。これが実現すれば、oxlint や oxfmt が .svelte ファイルを(prettier へのフォールバックではなく)ネイティブに処理できるようになり、ユーザーは rsvelte を意識することなく oxc ツールチェーンをそのまま使えるようになる。
Svelte 組織での公式メンテナンス。 これはまだ何も決まっていない、私が長期的に目指している方向性である。ツールチェーンにはコミュニティの信頼と継続性が不可欠であり、個人リポジトリのままでは限界がある。互換性を最優先する設計原則は、将来 Svelte 組織でのメンテナンスを提案できる水準に近づくための土台だと考えている。
まとめ
- AI エージェントが実装の主体になり、静的検査は「ループ毎に走るもの」になった。検査の所要時間は 1 ループの所要時間の下限であり、検査のリソース消費は並列度を制約する
- Rust / ネイティブベースのツールチェーンはこれを解決しつつあるが、
.svelteの Svelte 固有処理には JavaScript 実装が残っている - rsvelte は Svelte ツールチェーンのドロップイン代替を目標とする Rust 実装群である。言語仕様への独自拡張は加えず、切り替えも撤退も低コストであることを最優先する。到達度はパッケージごとに異なる
- Flyle 本番の型検査は rsvelte 化だけで 1.7 倍(51.4s → 30.6s、CPU 約 56% 減)、tsgo 化を合わせて 5.7 倍(9.0s)。ルールセットを揃えた Svelte 固有 Lint は約 20 倍。rsvelte-check 本体のメモリは約 0.12GB で、メモリの大半は TS エンジンが占める。公式ツールと併走して診断差分を確認しながら試せる
rsvelte はまだ発展途上のプロジェクトである。試して問題を見つけたら、GitHub で issue やフィードバックをもらえると嬉しい。
私が VPoT を務める 株式会社フライル では、現在ソフトウェアエンジニアを募集しています。 この記事の内容に共感いただけた方、AI 時代の開発基盤づくりに興味のある方、また事業内容に興味のある方は、ぜひカジュアル面談でお話ししましょう。