再開可能とハイドレーション
Qwik アプリケーションの重要な概念は、サーバーサイドレンダリングされた状態から再開可能であるということです。再開可能性を説明する最良の方法は、現在の世代のフレームワークがどのようにリプレイ可能か (ハイドレーション) を理解することです。
SSR/SSG アプリケーションがクライアントで起動すると、クライアント側のフレームワークが 3 つの情報を復元する必要があります。
- リスナー - イベントリスナーを見つけて DOM ノードにインストールし、アプリケーションをインタラクティブにします。
- コンポーネントツリー - アプリケーションコンポーネントツリーを表す内部データ構造を構築します。
- アプリケーションステート - サーバーでフェッチまたは
store
に保存されたデータを復元します。
これらをまとめてハイドレーションといいます。現在の世代のすべてのフレームワークは、アプリケーションをインタラクティブにするためにこのステップを必要とします。
- フレームワークは、現在のページに関連付けられたすべてのコンポーネントコードをダウンロードする必要があります。
- フレームワークは、リスナーの場所と内部コンポーネントツリーを再構築するために、ページ上のコンポーネントに関連付けられたテンプレートを実行する必要があります。
Qwik は、クライアントでアプリケーションを再開するためにハイドレーションを必要としないため、異なります。ハイドレーションを必要としないことが、Qwik アプリケーションの起動を瞬時に行えるようにしています。
他のすべてのフレームワークのハイドレーションは、クライアントですべてのアプリケーションロジックをリプレイします。Qwik は代わりにサーバーでの実行を一時停止し、クライアントでの実行を再開します。
再開可能性の紹介
再開可能性とは、すべてのアプリケーションロジックをリプレイおよびダウンロードすることなく、サーバーでの実行を一時停止し、クライアントでの実行を再開することです。
良いメンタルモデルは、Qwik アプリケーションはそのライフサイクルの任意の時点でシリアライズし、別の VM インスタンス (サーバーからブラウザー) に移動できるということです。そこで、アプリケーションはシリアライズが停止した場所から単純に再開します。ハイドレーションは必要ありません。したがって、Qwik アプリケーションはハイドレートせず、再開します。
これを実現するために、Qwik は、コードなし起動と互換性のある方法で、3 つの問題 (リスナー、コンポーネントツリー、アプリケーションステート) を解決する必要があります。
リスナー
イベントリスナーのない DOM は単なる静的なページであり、アプリケーションではありません。今日のすべてのサイトの標準は、非常に高いレベルのインタラクティビティであるため、最も静的に見えるサイトでさえ、イベントリスナーでいっぱいです。これらには、メニュー、ホバー、展開する詳細、または完全なインタラクティブアプリが含まれます。
既存のフレームワークは、コンポーネントをダウンロードし、テンプレートを実行して、DOM にアタッチされるイベントリスナーを収集することにより、イベントリスナーを解決します。現在のアプローチには、次の問題があります。
- テンプレートコードをすぐにダウンロードする必要がある。
- テンプレートコードをすぐに実行する必要がある。
- イベントハンドラーコードをすぐにダウンロードする必要がある (アタッチするため)。
上記のアプローチはスケーリングしません。アプリケーションがより複雑になるにつれて、すぐにダウンロードして実行する必要があるコードの量は、アプリケーションのサイズに比例して増加します。これは、アプリケーションの起動パフォーマンス、ひいてはユーザーエクスペリエンスに悪影響を与えます。他のフレームワークでは、アプリケーションのチャンクの遅延読み込み自体が、時間と労力を消費する開発タスクになります。Qwik では、遅延読み込みは、再開可能なアーキテクチャの自然な結果です。
Qwik は、イベントリスナーを次のように DOM にシリアライズすることで上記の問題を解決します。
<button on:click="./chunk.js#handler_symbol">click me</button>
Qwik は依然としてリスナー情報を収集する必要がありますが、このステップは SSR/SSG の一部として実行されます。SSR/SSG の結果は HTML にシリアライズされ、ブラウザーは実行を再開するために何もする必要はありません。on:click
属性には、すぐに何もせずにアプリケーションを再開するためのすべての情報が含まれていることに注意してください。
- Qwikloader は、DOM 要素ごとに多くの個別のリスナーではなく、単一のグローバルリスナーを設定します。このステップは、アプリケーションコードが存在しない状態で行うことができます。
- HTMLには、チャンクへのURLとシンボル名が含まれています。この属性は、Qwikloaderにダウンロードするコードチャンクと、チャンクから取得して実行するシンボルを指示します。
- 最後に、上記のすべてを可能にするために、Qwikのイベント処理実装は非同期性を理解しており、それによってクロージャを自動的に遅延ロードできます。
コンポーネントツリー
フレームワークはコンポーネントツリーを扱います。そのため、フレームワークは、どのコンポーネントをいつ再レンダリングする必要があるかを知るために、コンポーネントツリーを完全に理解する必要があります。既存のフレームワークのSSR/SSGの出力を見ると、コンポーネントの境界情報が失われています。結果として得られるHTMLを見ても、コンポーネントの境界がどこにあるかを知る方法はありません。この情報を再作成するために、フレームワークはコンポーネントテンプレートを再実行し、コンポーネント境界の位置をメモ化します。再実行がハイドレーションです。ハイドレーションは、コンポーネントテンプレートのダウンロードとその実行の両方が必要なため、コストがかかります。
Qwikは、SSR/SSGの一部としてコンポーネントの境界情報を収集し、その情報をHTMLにシリアライズします。その結果、Qwikは次のことが可能です。
- コンポーネントコードが実際に存在しなくても、コンポーネント階層情報を再構築できます。コンポーネントコードは遅延させることができます。
- Qwikは、すべてを事前にではなく、再レンダリングする必要があるコンポーネントに対してのみ、これを遅延的に行うことができます。
- Qwikは、ストアとコンポーネント間の関係情報を収集します。これにより、状態の変化の結果として、どのコンポーネントを再レンダリングする必要があるかをQwikに通知するサブスクリプションモデルが作成されます。サブスクリプション情報もHTMLにシリアライズされます。
アプリケーションの状態
既存のフレームワークは通常、アプリケーションの状態をHTMLにシリアライズして、ハイドレーションの一部として状態を復元できるようにする方法を備えています。この点で、それらはQwikと非常に似ています。ただし、Qwikは、コンポーネントのライフサイクルに状態管理をより緊密に統合しています。実際には、コンポーネントはコンポーネントの状態とは独立して遅延ロードできることを意味します。これは、コンポーネントのpropsが通常、親コンポーネントによって作成されるため、既存のフレームワークでは容易に実現できません。これにより、連鎖反応が生じます。コンポーネントXを復元するためには、その親も復元する必要があります。Qwikでは、親コンポーネントのコードが存在しなくても、任意のコンポーネントを再開できます。
シリアライズ
シリアライズについて考える最も簡単な方法は、JSON.stringify
を使用することです。ただし、JSONにはいくつかの制限があります。Qwikはいくつかの制限を克服できますが、克服できないものもあり、開発者ができることに制限が課せられます。Qwikアプリケーションを構築する際には、これらの制限を理解することが重要です。
Qwikが解決するJSONの制限
- JSONはDAGを生成します。DAGはDirected Acyclic Graphの略で、シリアライズされるオブジェクトが循環参照を持つことができないことを意味します。アプリケーションの状態はしばしば循環するため、これは大きな制限です。Qwikは、オブジェクトのグラフがシリアライズされるときに、循環参照が適切に保存され、その後復元されるようにします。
- JSONは一部のオブジェクト型をシリアライズできません。たとえば、DOM参照や日付などです。Qwikのシリアライズ形式は、このようなオブジェクトを正しくシリアライズして復元できるようにします。以下は、Qwikでシリアライズできる型のリストです。
- DOM参照
- Promise(リソースを参照)
- 関数クロージャ(QRLでラップされている場合)
- 日付
URL
オブジェクトMap
およびSet
インスタンス。
Qwikが解決しないJSONの制限
シリアライズが不可能な場合は、コードをクライアントのみで実行する必要があります。
シリアライズ可能性を考慮したアプリケーションの作成
フレームワークの再開可能性の機能は、アプリケーションの再開可能性にも拡張される必要があります。これは、フレームワークが、シリアライズしてから再開(再ブートストラップなし)できる方法で、アプリケーションのコンポーネントとエンティティを開発者が表現するためのメカニズムを提供する必要があることを意味します。これには、再開可能性の制約を考慮してアプリケーションを作成する必要があります。開発者がヒープ中心的な方法でアプリケーションを作成し続け、より優れたフレームワークが何とかこの最適でないアプローチを補うことを期待することは単純に不可能です。
開発者は、DOM中心的な方法でアプリケーションを作成する必要があります。これには、Web開発者の行動の変化とスキルの再編成が必要になります。フレームワークは、開発者がこの方法でアプリケーションを簡単に作成できるように、ガイダンスとAPIを提供する必要があります。
再開可能性のその他の利点
再開可能性を使用する最も明白な利点は、サーバーサイドレンダリングです。ただし、二次的な利点もあります
- ユーザーがアプリケーションに戻ったときにコンテキストを失わないように、既存のPWAアプリをシリアライズする
- 変更されたコンポーネントのみを再レンダリングする必要があるため、レンダリングパフォーマンスが向上する
- きめ細かい遅延ロード
- 特にモバイルデバイスでのメモリ負荷の軽減
- 既存の静的Webサイトのプログレッシブインタラクティビティ