はじめに
Remix Q&A
Q. Remixアプリは、サーバーとクライアントサイドにデプロイする必要がありますか?
A. はい、Remixを使用する場合、アプリケーションを完全に動作させるためには、サーバーサイドとクライアントサイドの両方にデプロイする必要があります。
- サーバーサイド(SSR):
- 役割: サーバーサイドレンダリング(SSR)を行い、初期ページロード時にHTMLを生成してクライアントに送信します。これにより、SEOが向上し、初期表示が高速化されます。また、サーバーサイドでAPIリクエストやデータベースとのやり取りを行います。
- 構成:
build/server/index.js
に生成されたサーバーHTTPハンドラーが使用されます。このハンドラーは、すべてのルートとモジュールを含み、サーバー上でのリクエスト処理を行います。
- クライアントサイド(CSR):
- 役割: クライアントサイドでのインタラクションを処理します。ユーザーがページ間を移動する際のトランジションや、動的なUI更新を行います。初期HTMLがロードされた後、クライアントサイドでJavaScriptが実行され、アプリケーションがインタラクティブになります。
- 構成:
build/client/
に生成された静的ファイル(JavaScript、CSS、画像など)が使用されます。これらのファイルは、ブラウザで実行されるアプリケーションのすべてのリソースを含みます。
- 追記
- SSRでは初期表示時にデータ取得済みで完全なHTMLができるので、SEOに有利という意味。
- CSRではデータなしでもスケルトンスクリーンが表示されるという意味では、高速。
Q. Remixではコンパイルが必要ですか?
A. はい、Remixアプリケーションをデプロイする際には、ソースコードをビルドし、サーバーサイドとクライアントサイドで使用するためのファイルを生成します。このプロセスには、ViteやWebpackといったビルドツールが使用されます。
- サーバーサイドビルド:
- サーバーHTTPハンドラーを生成します。これは通常、
build/server/index.js
に保存され、サーバー上でのレンダリングやリクエスト処理に使用されます。
- サーバーHTTPハンドラーを生成します。これは通常、
- クライアントサイドビルド:
- クライアントサイドのJavaScript、CSS、画像などの静的ファイルを生成します。これらは通常、
build/client/
ディレクトリに保存され、ブラウザで実行されるリソースを提供します。
- クライアントサイドのJavaScript、CSS、画像などの静的ファイルを生成します。これらは通常、
- アセットマニフェストの生成:
- クライアントとサーバーの両方で使用される依存関係グラフを含むアセットマニフェストを生成します。これにより、初期サーバーレンダリング時のリソースプリロードやクライアントサイド遷移時のプリフェッチが可能になります。
Q. Remixがサーバーではなく、ハンドラーとはどういう意味ですか?
A. Remixはサーバーそのものではなく、実際のJavaScriptサーバーに渡されるハンドラーです。RemixはNode.jsではなく、Web Fetch APIに基づいて構築されているため、Node.jsサーバー(Vercel、Netlify、Architectなど)や非Node.js環境(Cloudflare Workers、Deno Deployなど)で動作できます。
Remixはサーバーに依存しないハンドラーであり、特定のサーバーで動作させるために「アダプター」を使用します。アダプターは、サーバーのリクエスト/レスポンスAPIをFetch APIに変換し、逆にFetch APIのレスポンスをサーバーのレスポンスAPIに適応させます。
Express等がサーバー、Remixはそのサーバー上のハンドラー、@remix-run/expressパッケージはアダプターと呼ばれます。
アダプターは、サーバーのリクエストをFetch APIリクエストに適応させ、Remixのアプリケーションハンドラーを呼び出し、そのレスポンスをサーバーのレスポンスAPIに適応させます。この仕組みにより、Remixはどこでもデプロイ可能であり、既存のJavaScriptサーバーに段階的に導入することができます。
Q. RemixはMVC設計ですか?
A. はい、RemixのMVC(Model-View-Controller)設計ですが、従来のMVCフレームワークと異なる以下のような特徴があります。
- ルートモジュールによるViewとControllerの役割の統合:
- ルートモジュール: Remixでは、各ルート(URL)に対応するモジュールがあり、その中でデータのロード、アクションの処理、UIのレンダリングを行います。これにより、ViewとControllerの役割が統合され、コードがシンプルかつ直感的になります。
- exports: ルートモジュールは主に
loader
(データのフェッチ)、action
(データの変更)、およびdefault
(UIコンポーネント)の3つのエクスポートを持ちます。
- データのロードとアクションの処理:
- loader: データをサーバーサイドでロードし、SSRでHTMLを生成する際に使用されます。これにより、初期表示が高速化され、SEOも向上します。
- action: フォーム送信やその他のユーザーアクションに応じてデータを変更するためのロジックを定義します。
- UIとデータ操作の統合:
- UIコンポーネント: 各ルートモジュール内で定義されたReactコンポーネントは、対応するデータ操作ロジックと密接に結びついています。これにより、UIの状態管理が容易になります。
- シンプルなコード構造: データフェッチ、UIのレンダリング、アクションの処理が1つのファイルにまとめられているため、開発者は一貫性のある方法でアプリケーションを構築できます。
- サーバーとクライアントのシームレスな統合:
- SSRとCSRの統合: Remixはサーバーサイドレンダリング(SSR)とクライアントサイドレンダリング(CSR)の両方をシームレスに統合しています。これにより、初期表示の高速化とインタラクティブなUIの提供が両立できます。
- フェッチAPI: Fetch APIを使ったクッキーやセッション管理のヘルパーが用意されており、データのやり取りが簡素化されています。
- 段階的な導入とスケーラビリティ:
- 段階的導入: 既存のJavaScriptサーバーに段階的にRemixを導入することが可能です。これにより、既存のコードベースを徐々に移行しやすくなります。
- スケーラブルなアーキテクチャ: 必要に応じてアプリケーションのスケールアップが可能であり、初期段階ではシンプルに始め、後から機能を追加していくことができます。
Q. Remixのブラウザフレームワークの特徴は?
A. まず、ブラウザフレームワークとは、主にクライアントサイドで実行されるウェブアプリケーションの機能を提供し、ユーザーインターフェースを構築するためのフレームワークです。これらのフレームワークは、ブラウザ内で動作し、ユーザーの操作に対してリアルタイムで反応する動的なウェブアプリケーションを作成するためのツールとライブラリを提供します。
SSRによるレンダリングとCSRによるハイドレート
- Remixは、SSRが作成したHTMLドキュメントをブラウザに提供した後、ブラウザビルドのJavaScriptモジュールでページを「ハイドレート(再活性化)」します。これは、Remixが「ブラウザをエミュレートする」とよく言われる部分です。ハイドレーションという用語は、ウェブ開発におけるサーバーサイドレンダリングされた静的なHTMLに対して、クライアントサイドのJavaScriptを使って動的な機能を付加するプロセスを比喩的に表現したものです。この過程により、ページは迅速に表示され、インタラクティブな要素もスムーズに動作するようになります。
- ユーザーがリンクをクリックすると、ドキュメント全体とすべてのアセットをサーバーから取得するのではなく、次のページのデータだけをフェッチしてUIを更新します。
- ユーザーが<Form>を使ってデータを更新する際、通常のHTMLドキュメントリクエストを行う代わりに、ブラウザランタイムがサーバーにフェッチを行い、ページ上のすべてのデータを自動的に再検証し、Reactで更新します。
パフォーマンスの利点
- アセットを再ダウンロード(またはキャッシュから取得)する必要がない
- アセットをブラウザが再解析する必要がない
- フェッチされるデータはドキュメント全体よりもはるかに小さい
- RemixはHTML API (<a>と<form>)を強化しているため、ページがJavaScriptをロードする前でもアプリが動作する傾向がある
クライアントサイドナビゲーションの最適化
- Remixは、クライアントサイドナビゲーションのための最適化機能も持っています。URL間で持続するレイアウトを認識し、変更がある部分のデータだけをフェッチします。完全なドキュメントリクエストでは、すべてのデータをサーバーからフェッチする必要があり、バックエンドのリソースを浪費し、アプリの速度を低下させます。
- このアプローチは、サイドバーナビゲーションのスクロール位置をリセットしない、文書の先頭ではなく、より適切な場所にフォーカスを移動させるといったUXの向上にもつながります。
事前フェッチとリッチユーザーエクスペリエンス
- ユーザーがリンクをクリックする直前に、Remixは次のページのすべてのリソースを事前にフェッチすることもできます。ブラウザフレームワークはコンパイラのアセットマニフェストを認識しており、リンクのURLにマッチし、マニフェストを読み取って次のページのすべてのデータ、JavaScriptモジュール、CSSリソースを事前にフェッチします。これにより、ネットワークが遅くてもRemixアプリは高速に感じられます。
- RemixはクライアントサイドAPIも提供しており、HTMLとブラウザの基本モデルを変更することなく、リッチなユーザーエクスペリエンスを作成できます。
ユーザーエクスペリエンスの向上例
- フォーム送信中にボタンを無効にする
- サーバーサイドのフォーム検証が失敗した場合に入力にフォーカスを合わせる
- エラーメッセージをアニメーションで表示する