SSR(サーバーサイド レンダリング)を使用する動的ウェブアプリで Firebase を使用する

Firebase JS SDK や他の Firebase クライアント SDK を使用したことがあれば、FirebaseApp インターフェースと、それを使用したアプリ インスタンスの構成方法に精通している可能性があります。サーバーサイドで同様のオペレーションを容易にするために、Firebase には FirebaseServerApp が用意されています。

FirebaseServerApp は、サーバーサイド レンダリング(SSR)環境で使用される FirebaseApp のバリエーションです。これには、クライアントサイド レンダリング(CSR)とサーバーサイド レンダリングの境界にまたがる Firebase セッションを継続するためのツールが含まれています。これらのツールと戦略は、Firebase で構築され、Firebase App Hosting などの Google 環境にデプロイされた動的ウェブアプリを強化するのに役立ちます。

FirebaseServerApp を使用して、次の権限を付与します。

  • 完全な管理権限を持つ Firebase Admin SDK とは対照的に、ユーザー コンテキスト内でサーバーサイド コードを実行します。
  • SSR 環境で App Check を使用できるようにします。
  • クライアントで作成された Firebase Auth セッションを続行します。

FirebaseServerApp のライフサイクル

サーバーサイド レンダリング(SSR)フレームワークや、クラウド ワーカーなどの他のブラウザ以外のランタイムは、複数の実行間でリソースを再利用することで、初期化時間を最適化します。FirebaseServerApp は、参照数のメカニズムを使用してこのような環境に対応するように設計されています。アプリが以前の initializeServerApp と同じパラメータを使用して initializeServerApp を呼び出すと、すでに初期化されている同じ FirebaseServerApp インスタンスが返されます。これにより、不要な初期化のオーバーヘッドとメモリ割り当てを削減できます。FirebaseServerApp インスタンスで deleteApp を呼び出すと、参照数は減り、参照数がゼロになるとインスタンスが解放されます。

FirebaseServerApp インスタンスをクリーンアップする

FirebaseServerApp インスタンスで deleteApp を呼び出すタイミングを把握するのが難しい場合があります。特に、多くの非同期オペレーションを並列に実行している場合は困難です。FirebaseServerAppSettingsreleaseOnDeref フィールドを使用すると、この処理を簡素化できます。releaseOnDeref に、リクエストのスコープの存続期間が設定されたオブジェクト(SSR リクエストのヘッダー オブジェクトなど)への参照を割り当てると、フレームワークがこのヘッダー オブジェクトを再利用するときに、FirebaseServerApp の参照数が減ります。これにより、FirebaseServerApp インスタンスは自動的にクリーンアップされます。

releaseOnDeref の使用例を次に示します。

/// Next.js
import { headers } from 'next/headers'
import { FirebaseServerAppSettings, initializeServerApp} from "@firebase/app";

export default async function Page() {
  const headersObj = await headers();
  appSettings.releaseOnDeref = headersObj;
  let appSettings: FirebaseServerAppSettings = {};
  const serverApp = initializeServerApp(firebaseConfig, appSettings);
  ...
}

クライアントで作成された認証済みセッションを再開する

FirebaseServerApp のインスタンスが Auth ID トークンで初期化されている場合は、クライアントサイド レンダリング(CSR)環境とサーバーサイド レンダリング(SSR)環境の間で認証されたユーザー セッションをブリッジできます。Auth ID トークンを含む FirebaseServerApp オブジェクトで初期化された Firebase Auth SDK のインスタンスは、初期化時にユーザーのログインを試みます。その際に、アプリケーションがログイン方法を呼び出す必要はありません。

Auth ID トークンを指定すると、アプリはクライアントで任意の Auth のログイン方法を使用できるようになるため、ユーザー操作が必要なログイン方法であっても、セッションはサーバーサイドで確実に継続されます。また、認証された Firestore クエリなどの負荷の高いオペレーションをサーバーにオフロードできるため、アプリのレンダリング パフォーマンスが向上します。

/// Next.js
import { initializeServerApp } from "firebase/app";
import { getAuth } from "firebase/auth";

// Replace the following with your app's
// Firebase project configuration
const firebaseConfig = {
  // ...
};

const firebaseServerAppSettings = {
  authIdToken: token  // See "Pass client tokens to the server side
                      // rendering phase" for an example on how transmit
                      // the token from the client and the server.
}

const serverApp =
  initializeServerApp(firebaseConfig,
                      firebaseServerAppSettings);
const serverAuth = getAuth(serverApp);

// FirebaseServerApp and Auth will now attempt
// to sign in the current user based on provided
// authIdToken.

SSR 環境で App Check を使用する

App Check を適用する場合は、Firebase SDK が getToken の内部呼び出しに使用する App Check SDK インスタンスが使用されます。生成されたトークンは、すべての Firebase サービスへのリクエストに含まれるため、バックエンドでアプリを検証できます。

ただし、App Check SDK から特定のヒューリスティクスにアクセスしてアプリを検証するにはブラウザが必要になるため、サーバー環境では App Check SDK を初期化できません。

代わりに使用されるのが FirebaseServerApp です。FirebaseServerApp の初期化時にクライアントで生成された App Check トークンが指定された場合は、Firebase サービスが呼び出されるときに Firebase プロダクト SDK でこのトークンが使用されるため、App Check SDK インスタンスは必要なくなります。

/// Next.js
import { initializeServerApp } from "firebase/app";

// Replace the following with your app's
// Firebase project configuration
const firebaseConfig = {
  // ...
};

const firebaseServerAppSettings = {
  appCheckToken: token // See "Pass client tokens to the server side
                       // rendering phase" for an example on how transmit
                       // the token from the client and the server.
}

const serverApp =
  initializeServerApp(firebaseConfig,
                      firebaseServerAppSettings);

// The App Check token will now be appended to all Firebase service requests.

クライアント トークンをサーバーサイド レンダリング フェーズに渡す

認証済みの Auth ID トークン(および App Check トークン)をクライアントからサーバーサイド レンダリング(SSR)フェーズに送信するには、サービス ワーカーを使用します。この方法では、SSR をトリガーする取得リクエストをインターセプトし、リクエスト ヘッダーにトークンを追加します。

Firebase Auth Service Worker のリファレンス実装については、Service Worker によるセッション管理をご覧ください。また、FirebaseServerApp の初期化で使用するこれらのトークンをヘッダーから取得して解析する方法を示すコードについては、サーバーサイドの変更をご覧ください。