如果您使用过 Firebase JS SDK 或其他 Firebase 客户端 SDK,那么您可能会熟悉 FirebaseApp
接口以及如何使用它来配置应用实例。为了在服务器端实现类似操作,Firebase 提供了 FirebaseServerApp
。
FirebaseServerApp
是 FirebaseApp
的变体,在服务器端渲染 (SSR) 环境中使用。它包含的一些工具可用于继续跨客户端渲染 (CSR)/服务器端渲染 (SSR) 进行连接的 Firebase 会话。这些工具和策略有助于增强使用 Firebase 构建并在 Google 环境(例如 Firebase App Hosting)中部署的动态 Web 应用。
使用 FirebaseServerApp
来执行以下操作:
- 在用户上下文中执行服务器端代码,这与具有完全管理权限的 Firebase Admin SDK 相反。
- 在 SSR 环境中启用 App Check。
- 继续在客户端中创建的 Firebase Auth 会话。
FirebaseServerApp 生命周期
服务器端渲染 (SSR) 框架和其他非浏览器运行时(例如云工作器)通过在多次执行中重复使用资源来优化初始化时间。FirebaseServerApp
旨在通过使用引用计数机制来兼容这些环境。如果应用使用与之前的 initializeServerApp
相同的参数来调用 initializeServerApp
,则会收到已初始化的相同 FirebaseServerApp
实例。这可减少不必要的初始化开销和内存分配。对 FirebaseServerApp
实例调用 deleteApp
时,它会减少引用计数,并且实例会在引用计数达到零后释放。
清理 FirebaseServerApp
实例
要知道何时对 FirebaseServerApp
实例调用 deleteApp
并不容易,尤其是在并行运行多个异步操作时。FirebaseServerAppSettings
的 releaseOnDeref
字段有助于简化此工作。如果您为 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);
...
}
恢复在客户端创建的经过身份验证的会话
使用 Auth ID 令牌初始化 FirebaseServerApp
实例后,它可在客户端渲染 (CSR) 环境和服务器端渲染 (SSR) 环境之间连接经过身份验证的用户会话。使用包含身份验证 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 强制执行依赖于 App Check SDK 实例,Firebase SDK 使用该实例在内部调用 getToken
。然后,生成的令牌会包含在对所有 Firebase 服务的请求中,以便后端对应用进行验证。
不过,由于 App Check SDK 需要浏览器来访问特定的启发法以进行应用验证,因此无法在服务器环境中进行初始化。
FirebaseServerApp
提供了一种替代方案。如果在 FirebaseServerApp
初始化期间提供了客户端生成的 App Check 令牌,Firebase 产品 SDK 会在调用 Firebase 服务时使用该令牌,因此无需 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) 阶段,请使用 Service Worker。此方法涉及拦截触发 SSR 的提取请求和将令牌附加到请求标头。
如需查看 Firebase Auth Service Worker 的参考实现,请参阅使用 Service Worker 进行会话管理。另请参阅服务器端的变化,其中包含演示如何从标头中解析这些令牌以用于 FirebaseServerApp
初始化的代码。