SolidJS:真にリアクティブな JavaScript フレームワーク

5 分

1. フロントエンドフレームワークの「聖杯」:パフォーマンスと体験

React が仮想 DOM(Virtual DOM)を普及させて以来、VDOM はモダンなフロントエンドフレームワークの標準装備になったかのようです。メモリ上に仮想的な UI 表現を保持し、diff アルゴリズムで最小限の DOM 更新を計算することで、開発体験と多くの場面でのパフォーマンスを向上させます。

しかし、VDOM にコストがないわけではありません。それ自体がメモリを消費し、diff 処理にも計算コストがかかります。そこで一つの疑問が生まれます。VDOM を介さず、状態の変化を DOM に直接かつ正確に反映しながら、宣言的で React に似た開発体験を維持できるのでしょうか。

SolidJS はその答えを示しています。

2. SolidJS の核心:細粒度リアクティビティ(Fine-Grained Reactivity)

SolidJS は宣言的でリアクティブな JavaScript フレームワークです。JSX を使用するため React とよく似ていますが、その内部原理はまったく異なります。

SolidJS のコンパイラは JSX コードを最適なネイティブ DOM 操作へ変換します。VDOM は使用せず、リアクティブな「シグナル」(Signals)で構成される依存グラフを作ります。シグナルの値が変わると、そのシグナルを購読している「エフェクト」(Effects)または計算(Memos)だけが再実行されます。

常識を覆すメンタルモデル:コンポーネントは一度しか実行されない!

React では state や props が変化すると、コンポーネント関数全体が再実行されます。しかし SolidJS では、コンポーネント関数は 最初から最後まで一度しか実行されません

import { createSignal } from 'solid-js';

function Counter() {
  console.log('Component function runs!'); // 这句话只会在组件挂载时打印一次

  const [count, setCount] = createSignal(0);

  const increment = () => setCount(count() + 1);

  return (
    <button type="button" onClick={increment}>
      Count: {count()}
    </button>
  );
}

ボタンをクリックすると、count() シグナルの読み取り部分と、それに依存する DOM テキストノードだけが更新されます。Counter 関数自体は再実行されません。この「外科手術のような」更新こそが、SolidJS の卓越したパフォーマンスの源です。

3. 主要 API

SolidJS のリアクティブシステムは、主に三つの基本プリミティブで構成されています。

  • createSignal(initialValue): リアクティブなシグナルを作成し、getter と setter を返します。[count, setCount]
  • createEffect(() => {}): 「エフェクト」を作成します。内部で読み取られたすべてのシグナルを自動的に追跡し、そのいずれかが変化すると再実行されます。DOM を手動で操作するなどの副作用に適しています。
  • createMemo(() => {}): キャッシュされる派生計算値を作成します。内部で依存するシグナルが変化したときだけ再計算されます。
import { createSignal, createEffect } from 'solid-js';

function App() {
  const [firstName, setFirstName] = createSignal('John');
  const [lastName, setLastName] = createSignal('Smith');

  // createEffect 会在 firstName 或 lastName 变化时自动运行
  createEffect(() => {
    console.log(`Full name: ${firstName()} ${lastName()}`);
  });

  // ...
}

4. SolidJS を選ぶ理由

  • 卓越したパフォーマンス: さまざまな独立ベンチマークで SolidJS は上位に入ることが多く、ネイティブ JavaScript コードに非常に近い性能を示します。
  • 非常に小さなバンドルサイズ: VDOM ランタイムがないため、コアパッケージは非常に小さくなっています。
  • 慣れ親しんだ開発体験: React Hooks に慣れていれば、SolidJS をすぐに使い始められます。JSX とリアクティブプリミティブの組み合わせは強力で直感的です。
  • 真のリアクティビティ: そのモデルは MobX や Vue の Composition API に近いものですが、コンパイラによって実行時コストなしで実現されています。

結論

SolidJS はフロントエンドフレームワークの進化における重要な方向性を示しています。つまり、コンパイラによってビルド時により多くの処理を行い、実行時コードを減らしてパフォーマンスを高めるという方向です。宣言的な開発体験を犠牲にせず、仮想 DOM の制約から完全に離れられることを証明しています。最高のパフォーマンスを求めるアプリケーションにとって、SolidJS は非常に魅力的な選択肢です。