集成 Angular Universal

借助 Firebase 框架感知型 CLI,您可以将您的 Angular 应用部署到 Firebase,以向您的用户提供动态内容。

准备工作

在开始将应用部署到 Firebase 之前,请先了解以下要求和相关选项:

  • 拥有 Firebase CLI 12.1.0 或更高版本。请务必使用您首选的方法安装 CLI
  • 可选:在 Firebase 项目中启用结算功能(如果您计划使用 SSR,则必须完成此操作)

  • 可选:AngularFire

初始化 Firebase

首先,请为您的框架项目初始化 Firebase。对于新项目,您可以使用 Firebase CLI 完成初始化;对于现有项目,则可以通过修改 firebase.json 执行此操作。

初始化新项目

  1. 在 Firebase CLI 中,启用 Web 框架预览:
    firebase experiments:enable webframeworks
  2. 通过 CLI 运行初始化命令,然后按照提示操作:

    firebase init hosting

  3. 在看到“Do you want to use a web framework?(experimental)”后输入“yes”

  4. 选择您的托管用源目录;它可以包含一个现有的 Angular 应用。

  5. 如果出现提示,请选择“Angular”。

初始化现有项目

firebase.json 中的托管配置更改为使用 source 选项,而不是 public 选项。例如:

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

提供静态内容

初始化 Firebase 后,您可以使用标准部署命令来提供静态内容:

firebase deploy

预呈现动态内容

如需在 Angular 中预呈现动态内容,您需要设置 Angular Universal。Firebase CLI 需要使用 Express Engine,为此,请运行以下代码:

ng add @nguniversal/express-engine

如需了解详情,请参阅 Angular Universal 指南

添加预呈现网址

默认情况下,系统只会预呈现根目录。不过,您可以在 angular.json 中找到预呈现步骤,并添加更多路由:

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

如果您需要进一步自定义,Firebase 还会参照托管根目录中的 guessRoutesroutes.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 集成

如果将 Admin 软件包添加到浏览器 build 中,这些软件包会执行失败,因此不妨考虑将其添加到服务器模块中,并作为可选的依赖项进行注入:

// 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 集成

Web 框架感知型 Firebase 部署工具可以使用 Cookie 自动同步客户端和服务器的状态。可视需要在 Express res.locals 对象中添加经过身份验证的 Firebase 应用实例 (firebaseApp) 及当前登录的用户 (currentUser)。之后,可以通过 REQUEST 令牌(该令牌可从 @nguniversal/express-engine/tokens 进行导出)将这些信息注入到您的模块中。