はじめに
Reactやvueで作ったサイトが、表示は速いのにボタンを押してもしばらく反応しない――そんな経験はないでしょうか。これは「ハイドレーション」と呼ばれる処理が原因です。サーバーで描画したHTMLに対して、ブラウザ側でもう一度JavaScriptを実行し、イベントハンドラを一つずつ結びつけ直す作業が必要になるためです。ページが大きくなるほどこの処理は重くなり、体感速度を悪化させます。
Qwikはこの「ハイドレーション」という工程そのものをなくすという、思い切ったアプローチを取るフレームワークです。今回はQwikの考え方と、実際にコードを動かしながらその特徴を見ていきます。
Qwikとは
QwikはBuilder.io社が開発しているWebフレームワークで、「resumability(再開可能性)」という独自の概念によって、努力なしで瞬時に読み込まれるWebアプリを目指しています。JSXや関数コンポーネントなどReactに近い書き方を採用しているため、既存のReact経験者であれば学習コストを抑えて始められます。
主な特徴
- Resumability(再開可能性) - サーバーでレンダリングした状態をそのままシリアライズしてHTMLに埋め込み、ブラウザ側では状態の再構築(ハイドレーション)を行わずに「実行を再開」します
- 細粒度の遅延ロード - コンポーネント単位ではなく、イベントハンドラや副作用単位で自動的にコードを分割し、実際にユーザーが操作した瞬間にだけ該当するJSを読み込みます
- Batteries included - Vite、Vitest、Playwrightなどが標準で組み込まれており、
npm create qwik@latestだけで開発を始められます - Qwik City - ファイルベースルーティングやSSR/SSGを備えたフルスタックフレームワークが同梱されています
インストール
新規プロジェクトを作る場合は、CLIから対話形式でセットアップします。
npm create qwik@latest
既存プロジェクトにコアライブラリだけを追加する場合は以下の通りです。
npm install @builder.io/qwik
基本的な使い方
Qwikのコンポーネントは component$ で定義します。末尾の $ は「ここが遅延ロードの境界になる」ことを示すQwik独自の記法で、Qwikオプティマイザがこの印を目印にコードを自動分割します。状態管理には useSignal を使い、count.value のように値を読み書きします。
以下はカウンターの実装例です。ブラウザ上でそのまま編集・実行できます。
onClick$ のようにイベント名にも $ が付いているのが特徴です。このハンドラの中身は、実際にクリックされるまでブラウザにダウンロードされません。今回はesm.sh経由でその場でモジュールを読み込む都合上、通常のアプリで得られる「初期表示時のJS量ゼロ」までは再現できませんが、書き味そのものは本番と同じです。
実践的なユースケース
useStoreでオブジェクトの状態をまとめて管理する
useSignal は単一の値の管理に向いていますが、複数のプロパティを持つオブジェクトや配列をまとめて扱いたい場合は useStore を使います。プロパティの一部だけを更新しても、Qwikが変更を検知して該当箇所だけを再描画します。
以下はTODOリストの例です。入力した文字列を配列に追加していきます。
useTask$で値の変化を追跡して副作用を実行する
複数のSignalやStoreの値から別の値を導出したい場合は useTask$ を使います。track に渡した値が変化するたびに、コールバックが再実行されます。サーバー・クライアントどちらでも実行できるため、初期表示時の計算にも使えます。
以下は単価と数量から合計金額を自動計算する例です。
useVisibleTask$でブラウザ表示後にだけ処理を実行する
setInterval やDOM操作など、ブラウザ環境でしか実行できない処理には useVisibleTask$ を使います。名前の通り、コンポーネントが実際に画面に表示されたタイミングで初めて実行されるため、サーバーサイドレンダリングと共存させても安全です。
以下は1秒ごとに現在時刻を更新する時計の例です。cleanup に登録した処理は、コンポーネントが破棄されるタイミングで自動的に呼び出されます。
まとめ
Qwikは「ハイドレーションをなくす」という一点に振り切ることで、大規模なWebアプリでも初期表示のインタラクティブ性を犠牲にしないという明確な答えを出したフレームワークです。component$ や onClick$ といった $ 記法は最初こそ独特に感じますが、これはQwikオプティマイザがコードを自動分割するための目印であり、書き味自体はReactに近く違和感なく書けます。
useSignal によるシンプルな状態管理から、useStore でのオブジェクト管理、useTask$ や useVisibleTask$ による副作用の制御まで一通り体験してみると、Reactの useState や useEffect に慣れている方ほどスムーズに移行できるはずです。実際のプロジェクトでは、Qwik Cityを使ったファイルベースルーティングやSSR/SSGの機能も揃っているので、まずは npm create qwik@latest で公式のスターターを触ってみることをおすすめします。