はじめに
ノードベースのエディタを作りたい。でも使っているのはSvelteで、React Flowは使えない。そんな状況、ありませんか。
Svelte Flowは、あのReact Flowを開発しているxyflowチームが手がけたSvelte向けのノードベースUIライブラリです。GitHubで34,000スター以上を誇るxyflowプロジェクトの一部として、週間38,000インストールという実績を持っています。
正直なところ、最初は「React Flowの移植版でしょ」くらいに思っていたんです。でも触ってみたら、Svelteのリアクティビティをフル活用した設計になっていて、むしろSvelteらしさが際立っている。30代になって思うのは、先入観で判断しないことの大切さですね。
Svelte Flowとは
Svelte Flowは、ノードベースのエディタやインタラクティブなダイアグラムを構築するためのカスタマイズ可能なSvelteコンポーネントライブラリです。
xyflow社が開発・メンテナンスしており、npmでは@xyflow/svelteパッケージとして提供されています。MITライセンスのオープンソースなので、商用利用も問題なし。
現在のバージョンは1.4.1。React Flowとアーキテクチャを共有しているため、同等の機能とパフォーマンスが期待できます。
特徴・メリット
1. 箱から出してすぐ使える
ドラッグ、ズーム、パンニング、複数選択、要素の追加・削除。これらの機能が最初から組み込まれています。
個人的には、この「設定なしで動く」感覚が一番ありがたい。ゼロから実装すると膨大な時間がかかる機能が、インストールした瞬間から使える。
2. ノードは単なるSvelteコンポーネント
「Svelte Flow nodes are just Svelte components」というのが公式の謳い文句。普段書いているSvelteコンポーネントの知識がそのまま活かせます。
<script lang="ts">
import { Handle, Position } from '@xyflow/svelte'
export let data: { label: string }
</script>
<div class="custom-node">
<Handle type="target" position={Position.Top} />
<div>{data.label}</div>
<Handle type="source" position={Position.Bottom} />
</div>
<style>
.custom-node {
padding: 10px 20px;
border-radius: 5px;
background: white;
border: 1px solid #ddd;
}
</style>
TailwindやSvelteのスコープ付きCSSとの相性も良好。デザインの自由度が高いのはありがたい。
3. Svelteのリアクティビティを活用
Svelteのストアベースの状態管理と自然に統合できます。writableストアでノードやエッジを管理すれば、Svelteらしいリアクティブな実装が可能。
import { writable } from 'svelte/store'
import type { Node, Edge } from '@xyflow/svelte'
export const nodes = writable<Node[]>([])
export const edges = writable<Edge[]>([])
Reactのusestate地獄から解放されて、宣言的に状態を扱える。これがSvelteを使う理由なんだよな、と実感できる部分です。
4. プラグインが充実
- Background: グリッドやドットのバックグラウンド
- MiniMap: 全体を俯瞰できるミニマップ
- Controls: ズームイン・アウトのコントロール
- Panel: フローティングパネル
これ、意外と自分で作ると大変なんですよ。標準で用意されているのは時短になる。
5. TypeScriptフレンドリー
型定義がしっかりしているので、TypeScriptで書くときのストレスがない。エディタの補完も効くし、型安全に開発できます。
6. SSR対応
サーバーサイドレンダリングにも対応しているので、SvelteKitとの相性も抜群。SEOを気にするプロジェクトでも安心して使えます。
インストール方法
前提条件
Svelte 4以上、またはSvelte 5のプロジェクトが必要です。
インストール
npm install @xyflow/svelte
SvelteKitでの使用
SvelteKitを使っている場合は、SSR設定に注意が必要です。
// svelte.config.js
import adapter from '@sveltejs/adapter-auto'
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
const config = {
preprocess: vitePreprocess(),
kit: {
adapter: adapter()
}
}
export default config
基本的な使い方
シンプルなフロー
<script lang="ts">
import { writable } from 'svelte/store'
import {
SvelteFlow,
Background,
Controls,
type Node,
type Edge,
} from '@xyflow/svelte'
import '@xyflow/svelte/dist/style.css'
// 初期ノード
const nodes = writable<Node[]>([
{
id: '1',
position: { x: 0, y: 0 },
data: { label: '入力' },
type: 'input',
},
{
id: '2',
position: { x: 0, y: 100 },
data: { label: '処理' },
},
{
id: '3',
position: { x: 0, y: 200 },
data: { label: '出力' },
type: 'output',
},
])
// 初期エッジ(ノード間の接続線)
const edges = writable<Edge[]>([
{ id: 'e1-2', source: '1', target: '2' },
{ id: 'e2-3', source: '2', target: '3' },
])
</script>
<div style="height: 500px;">
<SvelteFlow {nodes} {edges} fitView>
<Background />
<Controls />
</SvelteFlow>
</div>
これだけでドラッグ可能なノード、接続可能なエッジ、ズーム・パンが動作します。Svelteのストアを渡すだけというシンプルさがいい。
カスタムノードの作成
<!-- CustomNode.svelte -->
<script lang="ts">
import { Handle, Position } from '@xyflow/svelte'
export let data: {
label: string
status: 'pending' | 'running' | 'completed'
}
const statusColors = {
pending: 'bg-gray-200',
running: 'bg-yellow-200',
completed: 'bg-green-200',
}
</script>
<div class="px-4 py-2 rounded-lg shadow-md {statusColors[data.status]}">
<Handle type="target" position={Position.Top} />
<div class="font-medium">{data.label}</div>
<div class="text-sm text-gray-600">{data.status}</div>
<Handle type="source" position={Position.Bottom} />
</div>
<!-- App.svelte -->
<script lang="ts">
import { SvelteFlow } from '@xyflow/svelte'
import CustomNode from './CustomNode.svelte'
const nodeTypes = {
custom: CustomNode,
}
// nodes, edges の定義...
</script>
<SvelteFlow {nodes} {edges} {nodeTypes} fitView />
Svelteコンポーネントとして実装できるので、propsもスロットも普通に使える。学習コストが低いのがありがたい。
エッジの接続イベント
<script lang="ts">
import { SvelteFlow, addEdge, type Connection } from '@xyflow/svelte'
function handleConnect(connection: Connection) {
edges.update((eds) => addEdge(connection, eds))
}
</script>
<SvelteFlow
{nodes}
{edges}
on:connect={({ detail }) => handleConnect(detail)}
fitView
/>
Svelteのイベントディスパッチャーで自然にイベントを受け取れる。Reactのコールバック地獄と比べると、コードの見通しが良い。
実践的なユースケース
ワークフロービルダー
n8nやZapierのような自動化ツールのインターフェース。トリガー→アクション→条件分岐といったフローを視覚的に組み立てられます。
const workflowNodes: Node[] = [
{
id: 'trigger',
type: 'trigger',
position: { x: 250, y: 0 },
data: { label: 'Webhook受信', icon: 'webhook' },
},
{
id: 'filter',
type: 'condition',
position: { x: 250, y: 100 },
data: { label: '条件分岐', condition: 'status === 200' },
},
{
id: 'action1',
type: 'action',
position: { x: 100, y: 200 },
data: { label: 'Slack通知' },
},
{
id: 'action2',
type: 'action',
position: { x: 400, y: 200 },
data: { label: 'DBに保存' },
},
]
マインドマップ
アイデア整理やブレインストーミング用のツール。
import { MarkerType, type Edge } from '@xyflow/svelte'
const mindMapEdges: Edge[] = [
{
id: 'e1-2',
source: 'main',
target: 'idea1',
type: 'smoothstep',
markerEnd: { type: MarkerType.ArrowClosed },
},
// ...
]
AIパイプライン設計
LangChainやFlowise的な、AIモデルの処理フローを設計するツール。入力→プロンプトテンプレート→LLM→出力パーサーといった流れを視覚化できます。
組織図・ER図
階層構造やエンティティ間の関係を表現。dagre等のレイアウトアルゴリズムと組み合わせると、自動配置も可能です。
注意点
親要素のサイズ指定
SvelteFlowは親要素の100%を占めるので、親要素に明示的なサイズが必要です。
<!-- NG: 高さが0になる -->
<div>
<SvelteFlow {nodes} {edges} />
</div>
<!-- OK: 高さを指定 -->
<div style="height: 500px;">
<SvelteFlow {nodes} {edges} />
</div>
これ、最初にハマるポイントなので覚えておくといいです。
スタイルの読み込み忘れ
デフォルトスタイルを読み込まないと、ノードやエッジが正しく表示されません。
import '@xyflow/svelte/dist/style.css'
React Flowとの比較
同じxyflowチームが開発しているため、APIはかなり似ています。主な違い:
| 項目 | Svelte Flow | React Flow |
|---|---|---|
| 状態管理 | Svelteストア | React hooks |
| イベント | on:connect | onConnect |
| バンドルサイズ | 比較的軽量 | Svelteより少し重い |
React Flowを使ったことがあれば、ほぼ同じ感覚で使えます。逆に言えば、Svelte Flowから入ってもReact Flowへの移行は簡単。
まとめ
Svelte Flowを使ってみて感じたこと:
- 学習コスト: Svelteの知識がそのまま活きる。1日で基本は把握できる
- カスタマイズ性: ノードもエッジも自由に設計可能
- Svelteらしさ: ストアベースの状態管理が自然
- パフォーマンス: 大量ノードでもスムーズ
- エコシステム: React Flowのドキュメントも参考にできる
正直なところ、ノードベースのUIを1から実装するのは相当な工数がかかります。ドラッグ、ズーム、接続線の描画、当たり判定...考えるだけで気が遠くなる。それがSvelte Flowなら、数時間で動くプロトタイプが作れる。
Svelteでワークフロービルダー、ノーコードツール、データパイプラインの可視化を検討しているなら、Svelte Flow一択ですね。
まだ触ったことがない人は、公式サイトのExamplesから試してみてください。React Flowと同様に豊富なサンプルがあるので、イメージが湧きやすいと思います。
