Angular Universal を統合する

Firebase フレームワーク対応の CLI を使用して Angular アプリケーションを Firebase にデプロイし、ユーザーに動的コンテンツを配信します。

始める前に

Firebase に Angular Universal アプリのデプロイを開始する前に、次の要件とオプションを確認してください。

  • Firebase CLI バージョン 11.14.2 以降。任意の方法で CLI をインストールしている。
  • 省略可: Firebase プロジェクトで課金が有効になっている(SSR を使用する場合は必須)。
  • 省略可: AngularFire

Firebase を初期化する

まず、フレームワーク プロジェクトで Firebase を初期化します。新しいプロジェクトの場合は Firebase CLI を使用します。既存のプロジェクトの場合は firebase.json を変更します。

新しいプロジェクトを初期化する

  1. Firebase CLI で、ウェブ フレームワークのプレビューを有効にします。
    firebase experiments:enable webframeworks
  2. CLI から初期化コマンドを実行し、プロンプトに沿って操作します。
    firebase init hosting
  3. ホスティング ソース ディレクトリを選択します。既存の Angular アプリを指定できます。
  4. [Dynamic web hosting with web framework] を選択します。
  5. [Angular] を選択します。

既存のプロジェクトを初期化する

firebase.json のホスティング構成を変更して、public オプションではなく source オプションを設定します。例:

{
  "hosting": {
    "source": "./path-to-your-angular-workspace"
  }
}

静的コンテンツを提供する

Firebase を初期化した後、標準のデプロイ コマンドで静的コンテンツを提供します。

firebase deploy

動的コンテンツを事前レンダリングする

Angular で動的コンテンツを事前レンダリングするには、Angular Universal を設定する必要があります。Firebase CLI では、次のような Express Engine を想定しています。

ng add @nguniversal/express-engine

詳しくは、Angular Universal のガイドをご覧ください。

事前レンダリング URL を追加する

デフォルトでは、ルート ディレクトリのみが事前レンダリングされます。別のルートを追加するには、angular.json の事前レンダリングのステップでルートを追加します。

{
  "prerender": {
    "builder": "@nguniversal/builders:prerender",
    "options": {
      "routes": [
        "/",
        "ANOTHER_ROUTE",
        "AND_ANOTHER"
      ]
    },
    "configurations": {
      /* ... */
    },
    "defaultConfiguration": "production"
  }
}

Firebase ではホスティング ルートの guessRoutes ファイルまたは routes.txt ファイルも参照します。さらにカスタマイズが必要な場合は、これらのファイルを使用します。オプションの詳細については、Angular の事前レンダリング ガイドをご覧ください。

省略可: サーバー モジュールを追加する

デプロイ

firebase deploy を使用してデプロイすると、Firebase はブラウザ バンドルとサーバー バンドルをビルドして、アプリケーションを事前レンダリングします。これらの要素は、Hosting と Cloud Functions for Firebase にデプロイされます。

カスタム デプロイ

Firebase CLI では、本番環境構成の概略図にサーバー、ビルド、事前レンダリングのステップが含まれていることを前提としています。

CLI の前提条件を調整する場合は、ng deploy を構成して、angular.json の構成を編集します。たとえば、serverTarget を削除して SSR を無効にし、事前レンダリングされたコンテンツのみを提供できます。

{
  "deploy": {
    "builder": "@angular/fire:deploy",
    "options": {
      "browserTarget": "app:build:production",
      "serverTarget": "app:server:production",
      "prerenderTarget": "app:prerender:production"
    }
  }
}

省略可: Firebase JS SDK との統合

サーバーとクライアントの両方のバンドルに Firebase JS SDK メソッドを含める場合は、ランタイム エラーが発生しないように、プロダクトの使用前に isSupported() を確認してください。すべてのプロダクトがすべての環境でサポートされているわけではありません。

省略可: Firebase Admin SDK との統合

管理バンドルがブラウザのビルドに含まれているとエラーが発生します。このバンドルはサーバー モジュールで提供し、オプションの依存関係として挿入することを検討してください。

// your-component.ts
import type { app } from 'firebase-admin';
import { FIREBASE_ADMIN } from '../app.module';

@Component({...})
export class YourComponent {

  constructor(@Optional() @Inject(FIREBASE_ADMIN) admin: app.App) {
    ...
  }
}

// app.server.module.ts
import * as admin from 'firebase-admin';
import { FIREBASE_ADMIN } from './app.module';

@NgModule({
  …
  providers: [
    …
    { provide: FIREBASE_ADMIN, useFactory: () => admin.apps[0] || admin.initializeApp() }
  ],
})
export class AppServerModule {}

// app.module.ts
import type { app } from 'firebase-admin';

export const FIREBASE_ADMIN = new InjectionToken<app.App>('firebase-admin');

SSR で完全な動的コンテンツを提供する

省略可: Firebase Authentication との統合

ウェブ フレームワーク対応の Firebase デプロイツールは、Cookie を使用してクライアントとサーバーの状態を自動的に同期させます。Express の res.locals オブジェクトには認証済みの Firebase アプリ インスタンス(firebaseApp)と現在ログインしているユーザー(currentUser)が含まれている場合があります。これらは REQUEST トークン(@ngglobal/express-engine/tokens からエクスポート)を介してモジュールに挿入できます。