はじめに
ノードベースのビジュアルプログラミングエディタ、最近よく見かけると思いませんか。Blenderのシェーダーノード、Unreal Engineのブループリント、n8nのワークフローエディタ。これらに共通するのは、処理の流れを視覚的に組み立てられるUIです。
GitHubで11,600スター、9年の歴史を持つRete.js。「ビジュアルプログラミングのためのTypeScriptファーストフレームワーク」として、かなりの存在感を放っています。
正直なところ、以前React Flowを使ってみて「ノードエディタはこれで十分かな」と思っていたんです。でもRete.jsを触ってみたら、データフローエンジンと制御フローエンジンが組み込まれているという設計思想に驚きました。単なる「見た目」だけでなく「処理」まで担うフレームワークだったんですよ。
Rete.jsとは
Rete.jsは、処理指向のノードベースエディタを構築するためのカスタマイズ可能なTypeScriptファーストフレームワークです。
名前の「Rete」はラテン語で「ネットワーク」を意味します。まさにノード(節点)とコネクション(接続)でネットワークを構築するという、このフレームワークの本質を表している。
React.js、Vue.js、Angular、Svelte、Litと、主要なフロントエンドフレームワークをすべてサポート。MITライセンスのオープンソースなので、商用利用も問題なし。
特徴・メリット
1. TypeScriptファースト
個人的には、これが一番のポイントだと思っています。最初からTypeScriptで設計されているので、型推論がしっかり効く。
import { ClassicPreset } from 'rete'
class NumberNode extends ClassicPreset.Node {
constructor(initial: number) {
super('Number')
this.addOutput('value', new ClassicPreset.Output(socket, 'Number'))
this.addControl(
'value',
new ClassicPreset.InputControl('number', { initial })
)
}
}
エディタの補完も効くし、型安全に開発できる。30代になって思うのは、型の恩恵をフルに受けられる環境の快適さですね。
2. データフロー&制御フローエンジン
これ、意外と他のライブラリにない機能なんですよ。Rete.jsはノードの「見た目」だけでなく「処理」も担当します。
- データフローエンジン: 入力から出力へデータを流す処理
- 制御フローエンジン: 条件分岐やループなどの制御構造
- ハイブリッドエンジン: 両者の組み合わせ
ノードエディタを「ただのUI」ではなく「実行可能なグラフ」として扱える。この設計思想はかなり実用的。
3. マルチフレームワーク対応
React、Vue、Angular、Svelte、Lit。好きなフレームワークで実装できます。
プロジェクトで使っているフレームワークがそのまま使えるのは、コスパ的にも学習コスト的にもありがたい。
4. プラグインアーキテクチャ
モジュラーな設計になっていて、必要な機能だけを追加できます。
- rete-area-plugin: ズーム、パン、ノードのドラッグ
- rete-connection-plugin: ノード間の接続線
- rete-render-utils: レンダリングユーティリティ
- rete-react-plugin: Reactでのレンダリング
必要なものだけ入れればバンドルサイズも抑えられる。時短になる。
5. オンラインスタジオ
studio.retejs.orgで、ブラウザ上でエディタを試せます。コードを書く前にイメージを掴めるのは助かる。
インストール方法
Rete Kitを使用(推奨)
一番簡単なのはRete Kitを使う方法です。
npx rete-kit app
対話形式でフレームワーク(React、Vue、Angular、Svelte)を選択すると、プロジェクトがセットアップされます。
手動インストール
Reactの場合:
npm i rete rete-area-plugin rete-connection-plugin rete-render-utils rete-react-plugin
Vueの場合:
npm i rete rete-area-plugin rete-connection-plugin rete-render-utils rete-vue-plugin
TypeScript 4.7以上が必要なので、バージョンには注意してください。
CDNを使用
HTMLに直接読み込む方法もあります。
<script src="https://cdn.jsdelivr.net/npm/rete/rete.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/rete-area-plugin/rete-area-plugin.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/rete-connection-plugin/rete-connection-plugin.min.js"></script>
プロトタイプ作成には便利かもしれない。
基本的な使い方
エディタの基本構成
import { NodeEditor, ClassicPreset } from 'rete'
import { AreaPlugin, AreaExtensions } from 'rete-area-plugin'
import { ConnectionPlugin, Presets as ConnectionPresets } from 'rete-connection-plugin'
import { ReactPlugin, Presets as ReactPresets } from 'rete-react-plugin'
// ソケットの定義(ノード間の接続点)
const socket = new ClassicPreset.Socket('Number')
// ノードの定義
class NumberNode extends ClassicPreset.Node {
constructor(initial: number) {
super('Number')
this.addOutput('value', new ClassicPreset.Output(socket, 'Number'))
this.addControl(
'value',
new ClassicPreset.InputControl('number', { initial })
)
}
}
class AddNode extends ClassicPreset.Node {
constructor() {
super('Add')
this.addInput('a', new ClassicPreset.Input(socket, 'A'))
this.addInput('b', new ClassicPreset.Input(socket, 'B'))
this.addOutput('sum', new ClassicPreset.Output(socket, 'Sum'))
}
}
// エディタの初期化
async function createEditor(container: HTMLElement) {
const editor = new NodeEditor<Schemes>()
const area = new AreaPlugin<Schemes, AreaExtra>(container)
const connection = new ConnectionPlugin<Schemes, AreaExtra>()
const render = new ReactPlugin<Schemes, AreaExtra>()
// プラグインの登録
editor.use(area)
area.use(connection)
area.use(render)
// プリセットの適用
connection.addPreset(ConnectionPresets.classic.setup())
render.addPreset(ReactPresets.classic.setup())
// ノードの作成
const a = new NumberNode(1)
const b = new NumberNode(2)
const add = new AddNode()
await editor.addNode(a)
await editor.addNode(b)
await editor.addNode(add)
// ノードの接続
await editor.addConnection(new ClassicPreset.Connection(a, 'value', add, 'a'))
await editor.addConnection(new ClassicPreset.Connection(b, 'value', add, 'b'))
// ズームフィット
AreaExtensions.zoomAt(area, editor.getNodes())
return { editor, area }
}
これで数値を入力して足し算するノードエディタができます。普通のTypeScriptの知識がそのまま活かせるのがいいですね。
データフローエンジンの使用
import { DataflowEngine } from 'rete-engine'
// ノードにデータ処理を追加
class AddNode extends ClassicPreset.Node {
constructor() {
super('Add')
this.addInput('a', new ClassicPreset.Input(socket, 'A'))
this.addInput('b', new ClassicPreset.Input(socket, 'B'))
this.addOutput('sum', new ClassicPreset.Output(socket, 'Sum'))
}
// データフロー処理
data(inputs: { a?: number[], b?: number[] }) {
const a = inputs.a?.[0] || 0
const b = inputs.b?.[0] || 0
return { sum: a + b }
}
}
// エンジンの初期化と実行
const engine = new DataflowEngine<Schemes>()
editor.use(engine)
// 結果の取得
const result = await engine.fetch(add.id)
console.log(result.sum) // 3
ノードを接続するだけでなく、実際に処理を実行できる。これ、ワークフローエンジンを作るときにめちゃくちゃ便利。
Reactコンポーネントでの使用
import { useRete } from 'rete-react-plugin'
function App() {
const [ref, editor] = useRete(createEditor)
return (
<div>
<div ref={ref} style={{ width: '100%', height: '500px' }} />
<button onClick={() => console.log(editor?.getNodes())}>
ノード一覧
</button>
</div>
)
}
useReteフックを使えば、Reactアプリに簡単に組み込める。
実践的なユースケース
1. コード生成ツール
ノードを接続してコードを自動生成するツール。Scratchのような教育用プログラミング環境の構築に使えます。
class FunctionNode extends ClassicPreset.Node {
constructor(name: string) {
super('Function')
this.addInput('params', new ClassicPreset.Input(socket, 'Parameters'))
this.addOutput('code', new ClassicPreset.Output(socket, 'Code'))
this.addControl('name', new ClassicPreset.InputControl('text', { initial: name }))
}
data(inputs: { params?: string[] }) {
const name = this.controls.name.value
const params = inputs.params?.join(', ') || ''
return { code: `function ${name}(${params}) { }` }
}
}
2. 3Dマテリアルエディタ
BlenderやUnityのシェーダーグラフのような、視覚的なマテリアル編集ツール。
色、テクスチャ、数値を組み合わせてシェーダーを構築できます。
3. チャットボットフロー設計
会話の流れを視覚的に設計するツール。条件分岐、ユーザー入力、APIコールなどをノードとして表現できます。
4. データ変換パイプライン
ETL(Extract, Transform, Load)処理を視覚的に設計。CSVの読み込み→フィルタリング→変換→出力といったフローを構築できます。
5. 3D/AR/VR統合
Three.jsやA-Frameと組み合わせて、3D空間内にノードエディタを配置。VR空間でビジュアルプログラミングする未来が見えます。
React Flowとの比較
同じノードエディタ系のライブラリとして比較されることが多いので、簡単に整理しておきます。
| 項目 | Rete.js | React Flow |
|---|---|---|
| 対応フレームワーク | React, Vue, Angular, Svelte, Lit | React |
| 処理エンジン | データフロー&制御フロー内蔵 | なし(UIのみ) |
| TypeScript | ファースト | サポート |
| スター数 | 11.6k | 34k |
| 用途 | 処理指向のエディタ | UI/可視化指向 |
React Flowは「見た目のためのノードエディタ」、Rete.jsは「処理も含めたノードエディタ」という棲み分け。
どちらがいいかは用途次第ですが、ノードの処理を実行したいならRete.js一択ですね。
注意点
コンテナのサイズ指定
親要素に明示的なサイズが必要です。
// NG: 高さが0になる可能性
<div ref={ref} />
// OK: 高さを指定
<div ref={ref} style={{ width: '100%', height: '500px' }} />
これ、最初にハマるポイントなので覚えておくといいです。
TypeScriptバージョン
TypeScript 4.7以上が必要です。古いプロジェクトでは確認が必要。
学習コスト
React Flowより概念が多い。エディタ、エリア、エンジン、プラグインの関係を理解する必要があります。ただ、公式ドキュメントが充実しているので、順を追って読めば大丈夫。
まとめ
Rete.jsを使ってみて感じたこと:
- TypeScriptファースト: 型安全な開発ができる
- 処理エンジン内蔵: ノードの「見た目」だけでなく「処理」も担当
- マルチフレームワーク: React、Vue、Angular、Svelte、Litに対応
- プラグイン設計: 必要な機能だけ追加できる
- 9年の歴史: 安定した実績がある
正直なところ、ビジュアルプログラミングエディタを1から実装するのは相当な工数がかかります。ノードの描画、接続線の計算、処理の実行...考えるだけで気が遠くなる。それがRete.jsなら、データフローエンジンまで含めて数時間で動くプロトタイプが作れる。
ワークフローエンジン、ノーコードツール、教育用プログラミング環境。こういったプロジェクトで「処理も含めたノードエディタ」が必要なら、Rete.jsを検討してみてください。
まずはstudio.retejs.orgでオンラインスタジオを試してみることをおすすめします。コードを書く前にイメージが掴めると思います。