シングルページアプリケーション (SPA)
React Router をフレームワークとして使用する場合、react-router.config.ts ファイルで ssr:false を設定することで「SPA モード」を有効にできます。これにより、ランタイムサーバーレンダリングが無効になり、ビルド時に index.html が生成され、SPA として提供およびハイドレートできます。
一般的なシングルページアプリケーションは、ほとんど空の index.html テンプレートを送信し、空の <div id="root"></div> 程度しか含まれていません。対照的に、react-router build (SPA モード) は、ビルド時にルートルートを事前にレンダリングして index.html ファイルを作成します。これは、次のことを意味します。
- 空の
<div>以上のものを送信できる - ルート
loaderを使用してアプリケーションシェルのデータをロードできる - React コンポーネントを使用して、ユーザーが最初に表示するページを生成できる (ルート
HydrateFallback) - UI を変更せずに、後でサーバーレンダリングを再度有効にできる
1. ランタイムサーバーレンダリングを無効にする
サーバーレンダリングはデフォルトで有効になっています。react-router.config.ts で ssr フラグを false に設定して無効にします。
import { type Config } from "@react-router/dev/config";
export default {
ssr: false,
} satisfies Config;これを false に設定すると、サーバービルドは生成されなくなります。
ssr:false を設定すると、ランタイムサーバーレンダリング のみが無効になることに注意することが重要です。React Router は、index.html ファイルを生成するために、ビルド時 にルートルートをサーバーレンダリングします。そのため、プロジェクトは @react-router/node に依存する必要があり、ルートは SSR セーフである必要があります。つまり、サーバーレンダリングが無効になっている場合でも、最初のレンダリング中に window やその他のブラウザ専用 API を呼び出すことはできません。
2. HydrateFallback とオプションの loader をルートルートに追加する
SPA モードは、SPA のエントリポイントとして提供できる index.html ファイルをビルド時に生成します。これはルートルートのみをレンダリングするため、アプリケーション内の任意のパスでランタイムにハイドレートできます。
空の <div> よりも優れたローディング UI を提供するために、ルートルートに HydrateFallback コンポーネントを追加して、ビルド時にローディング UI を index.html にレンダリングできます。これにより、SPA のロード/ハイドレート中に、ユーザーにすぐに表示されます。
import LoadingScreen from "./components/loading-screen";
export function Layout() {
return <html>{/*...*/}</html>;
}
export function HydrateFallback() {
return <LoadingScreen />;
}
export default function App() {
return <Outlet />;
}ルートルートはビルド時にサーバーレンダリングされるため、必要に応じてルートルートで loader を使用することもできます。この loader はビルド時に呼び出され、データはオプションの HydrateFallback loaderData プロパティを介して利用可能になります。
import { Route } from "./+types/root";
export async function loader() {
return {
version: await getVersion(),
};
}
export function HydrateFallback({
loaderData,
}: Route.ComponentProps) {
return (
<div>
<h1>Loading version {loaderData.version}...</h1>
<AwesomeSpinner />
</div>
);
}これらのページをプリレンダリングしていない限り、SPA モードを使用している場合は、アプリ内の他のルートに loader を含めることはできません。
3. クライアントローダーとクライアントアクションを使用する
サーバーレンダリングが無効になっている場合でも、clientLoader と clientAction を使用してルートデータとミューテーションを管理できます。
import { Route } from "./+types/some-route";
export async function clientLoader({
params,
}: Route.ClientLoaderArgs) {
let data = await fetch(`/some/api/stuff/${params.id}`);
return data;
}
export async function clientAction({
request,
}: Route.ClientActionArgs) {
let formData = await request.formData();
return await processPayment(formData);
}4. すべての URL を index.html にリダイレクトする
react-router build を実行した後、build/client ディレクトリを任意の静的ホストにデプロイします。
一般的な SPA のデプロイと同様に、ホストがすべての URL をクライアントビルドの index.html にリダイレクトするように構成する必要があります。一部のホストはデフォルトでこれを行いますが、そうでないホストもあります。例として、ホストはこれを実行するために _redirects ファイルをサポートする場合があります。
/* /index.html 200
アプリの有効なルートで 404 エラーが発生する場合は、ホストを構成する必要がある可能性があります。