使用 Next.js 应用部署到 Firebase App Hosting

1. 准备工作

在此 Codelab 中,您将了解如何使用名为 Friendly Eats 的 Next.js Web 应用部署到 Firebase App Hosting,该应用是一个餐厅评价网站。

FRIEND Eats Web 应用

完成后的 Web 应用提供了一些实用功能,展示了 Firebase 如何帮助您构建 Next.js 应用。

  • 自动构建和部署:此 Codelab 将向您展示如何使用 Firebase App Hosting 在每次推送到已配置的分支时自动构建和部署 Next.js 代码。
  • 登录和退出:完成后的 Web 应用可让用户使用 Google 账号登录/退出。用户登录和保留功能完全通过 Firebase Authentication 进行管理。
  • 图片:完成后的 Web 应用可让登录用户上传餐馆图片。图片素材资源存储在 Cloud Storage for Firebase 中。Firebase JavaScript SDK 提供了已上传图片的公开网址。然后,此公开网址将存储在 Cloud Firestore 内的相关餐馆文档中。
  • 过滤条件:完成后的 Web 应用可让登录用户根据类别、位置和价格过滤餐馆列表。您还可以自定义所使用的排序方法。系统会从 Cloud Firestore 访问数据,并根据所使用的过滤条件应用 Firestore 查询。
  • 评价:完成后的 Web 应用支持登录用户发布对餐厅的评价,其中包含星级评分和基于文本的消息。评价信息存储在 Cloud Firestore 中。
  • 评价摘要:完成后的 Web 应用会自动使用 Gemini 模型总结评价。AI 生成的摘要存储在 Cloud Firestore 中。

前提条件

  • 了解 Next.js 和 JavaScript 相关知识

学习内容

  • 如何将 Firebase 与 Next.js 应用路由器和服务器端渲染搭配使用
  • 如何仅使用服务器端 Secret 授权对 Gemini API 的调用

您需要满足的条件

  • 您所选的浏览器(例如 Google Chrome)
  • 访问 IDX.dev(基于 Web 的工作区)
  • 一个用于创建和管理 Firebase 项目的 Google 账号
  • 一个 GitHub 账号(不一定需要与上述电子邮件账号相同)

2. 设置开发环境和 GitHub 代码库

此 Codelab 提供了应用的起始代码库,并依赖于 Firebase CLI 和 IDX.dev。

创建新的 GitHub 代码库并将其导入到 IDX 中

借助 Firebase App Hosting,您可以设置 GitHub 代码库,以便在每次推送到配置的分支时构建和部署 Next.js 代码。

  1. 为此 Codelab 创建一个新的 GitHub 代码库:https://github.com/new。您可以随意为其命名,例如 MyFriendlyEatsCodelab
  2. 复制新代码库的网址。它将如下所示:
    https://github.com/USER_NAME/REPOSITORY_NAME.git
  3. 前往 https://idx.google.com 并登录。
  4. 点击导入代码库,然后粘贴您复制的 GitHub 网址。
    IDX 会提示您关联到 GitHub,然后克隆您的(空)代码库。

查看 Codelab 的源代码库

您可以在 https://github.com/firebase/friendlyeats-web 查看 Codelab 源代码。friendlyeats-web 代码库包含适用于多个平台的示例项目。

您正在完成的此 Codelab 仅侧重于 Firebase App Hosting 和 Gemini API,是完整版 Codelab“将 Firebase 与 Next.js 应用集成”的简化版。此简短的 Codelab 要求您仅使用 friendlyeats-web 代码库的 #io-connect 分支中的源代码,特别是 nextjs-step10 目录中的源代码。

请注意 friendlyeats-web 代码库中的以下其他目录。虽然您在此 Codelab 中不需要这些目录,但了解它们很有帮助。

将 Codelab 源代码复制到新代码库中

以下是将 nextjs-step10 目录复制到您自己的代码库中的方法:

  1. 在 IDX 中,依次选择菜单 > 终端 > 新终端,打开终端。
  2. 使用 giget npm 软件包仅从 io-connect 分支中提取 nextjs-step10 目录:
    npx giget@latest gh:firebase/friendlyeats-web/nextjs-step10#io-connect . --force
    
  3. 使用 Git 在本地跟踪更改:
    git add -A
    git commit -m "codelab starting point"
    git branch -M main
    git push -u origin main
    

您现在应该会在 GitHub 代码库中看到起始代码。

3. 查看起始代码库

在本部分中,您将复习应用起始代码库中的几个部分,以便在此 Codelab 中向这些部分添加功能。

文件夹和文件结构

下表简要介绍了应用的文件夹和文件结构:

文件夹和文件

说明

src/components

适用于过滤条件、标题、餐馆详细信息和评价的 React 组件

src/lib

不一定绑定到 React 或 Next.js 的实用函数

src/lib/firebase

Firebase 专属代码和 Firebase 配置

public

Web 应用中的静态资源,例如图标

src/app

使用 Next.js 应用路由器进行路由

src/app/restaurant

API 路由处理程序

package.jsonpackage-lock.json

使用 npm 的项目依赖项

next.config.js

Next.js 专属配置(已启用服务器操作)

jsconfig.json

JavaScript 语言服务配置

服务器和客户端组件

该应用是使用应用路由器的 Next.js Web 应用。整个应用都会使用服务器渲染。例如,src/app/page.js 文件是负责主页面的服务器组件。src/components/RestaurantListings.jsx 文件是一个客户端组件,由文件开头的 "use client" 指令表示。

Import 语句

在某些文件中,您可能会注意到如下 import 语句:

import RatingPicker from "@/src/components/RatingPicker.jsx";

应用使用 @ 符号来避免复杂的相对导入路径,这是通过路径别名实现的。

Firebase 专属 API

所有 Firebase API 代码都封装在 src/lib/firebase 目录中。然后,各个 React 组件会从 src/lib/firebase 目录导入封装的函数,而不是直接导入 Firebase Functions 函数。

模拟数据

模拟餐厅和评价数据包含在 src/lib/randomData.js 文件中。该文件中的数据会汇编在 src/lib/fakeRestaurants.js 文件的代码中。

4. 设置您的 Firebase 项目

在本部分中,您将设置一个 Firebase 项目,并向其关联一个 Firebase Web 应用。您还将设置示例 Web 应用使用的 Firebase 服务。

创建 Firebase 项目

  1. 使用您在上一步中使用的同一 Google 账号登录 Firebase 控制台
  2. 点击相应按钮以创建新项目,然后输入项目名称(例如 FriendlyEats Codelab)。
  3. 点击继续
  4. 如果看到相关提示,请查看并接受 Firebase 条款,然后点击继续
  5. (可选)在 Firebase 控制台中启用 AI 辅助功能(称为“Gemini in Firebase”)。
  6. 在此 Codelab 中,您不需要使用 Google Analytics,因此请关闭 Google Analytics 选项。
  7. 点击创建项目,等待项目完成预配,然后点击继续

升级您的 Firebase 定价方案

如需使用 Firebase App Hosting 和 Cloud Storage for Firebase,您的 Firebase 项目必须采用随用随付 (Blaze) 定价方案,这意味着该项目与一个 Cloud Billing 账号相关联。

  • Cloud Billing 账号要求提供付款方式,例如信用卡。
  • 如果您刚开始接触 Firebase 和 Google Cloud,请确认您是否有资格获得 $300 赠金和免费试用 Cloud Billing 账号
  • 如果您是在活动中完成此 Codelab,请询问活动组织者是否有可用的 Cloud 积分。

如需将项目升级到 Blaze 方案,请按以下步骤操作:

  1. 在 Firebase 控制台中,选择升级您的方案
  2. 选择 Blaze 方案。按照屏幕上的说明将 Cloud Billing 账号与您的项目相关联。
    如果您需要在此升级过程中创建 Cloud Billing 账号,则可能需要返回 Firebase 控制台中的升级流程以完成升级。

5. 创建 App Hosting 后端

在本部分中,您将设置一个 App Hosting 后端来监控 Git 代码库中的分支。您还需要配置后端将与之通信的所有服务。

在本部分结束时,您将拥有一个与 GitHub 中的代码库相关联的 App Hosting 后端,每当您将新提交推送到 main 分支时,该后端都会自动重新构建并推出新版应用。

创建一个后端

  1. 在 Firebase 控制台中,前往 App Hosting 页面App Hosting 控制台的初始状态,其中包含“开始使用”按钮
  2. 点击开始以启动后端创建流程。
  3. 按照提示导入并关联您之前创建的 GitHub 代码库。
  4. 设置部署设置:
    • 将根目录保留为 /
    • 将正式版分支设置为 main
    • 启用自动发布
  5. 将后端命名为 friendlyeats-codelab(或您选择的后端名称)。这会成为用于访问后端的网域的一部分。
    此工作流还会自动在您的 Firebase 项目中创建一个 Firebase Web 应用。在此 Codelab 的后续环节中,您将使用此 Web 应用的配置值将代码库连接到 Firebase 项目。
  6. 点击完成并部署。稍等片刻,系统会将您转到新页面,您可以在该页面上查看新应用托管后端的运行状态!
  7. 在应用托管信息中心内,复制您的新网域。
    该网域的格式类似于 BACKEND_ID--PROJECT_ID.REGION.hosted.app。您稍后需要使用此网域来设置 Firebase Authentication。

由于 DNS 传播和 SSL 证书创建,网域可能需要几分钟才能开始正常运行。在后端创建期间,继续设置 Firebase 项目的其余部分并配置后端(本 Codelab 的后续步骤)。

每次将新提交推送到 GitHub 代码库的 main 分支时,您都会在 Firebase 控制台中看到新的构建和发布开始,并且您的网站会在发布完成后自动更新。

6. 设置其他 Firebase 服务

虽然此 Codelab 仅侧重于 Firebase App Hosting 和 Gemini API,但正常运行的 Web 应用需要其他 Firebase 服务才能正常运行。用于使所有这些服务在您的应用中正常运行的代码是您复制到自己的 GitHub 代码库中的代码库的一部分,但您仍需要在 Firebase 项目中设置这些服务。

设置身份验证

  1. 在 Firebase 控制台中,前往身份验证
  2. 点击开始使用
  3. 其他提供商列中,点击 Google > 启用
    1. 项目的公开名称文本框中,输入一个名称,例如 My FriendlyEatsCodelab app
    2. 项目的支持电子邮件地址下拉列表中,选择您的电子邮件地址。
    3. 点击保存
  4. 点击身份验证页面中的设置标签页。
    1. 点击屏幕左侧菜单中的授权网域
    2. 点击添加网域,然后添加您新建的应用托管网域(以 .hosted.app 结尾)。
    3. 点击添加进行保存。

设置 Cloud Firestore

  1. 在 Firebase 控制台的左侧面板中,展开构建,然后选择 Firestore 数据库
  2. 点击创建数据库
  3. 数据库 ID 保留为 (default)
  4. 为数据库选择一个位置,然后点击下一步
    对于真实应用,您需要选择靠近用户的位置。
  5. 点击以测试模式开始。阅读有关安全规则的免责声明。
    在本 Codelab 的后面部分,您将添加安全规则来保护您的数据。在没有为数据库添加安全规则的情况下,请不要公开分发或公开应用。
  6. 点击创建

设置 Cloud Storage for Firebase

  1. 在 Firebase 控制台的左侧面板中,展开构建,然后选择存储
  2. 点击开始使用
  3. 为默认存储分区选择位置。
    US-WEST1US-CENTRAL1US-EAST1 中的存储分区可为 Google Cloud Storage 使用“始终免费”层级。所有其他位置的存储分区都遵循 Google Cloud Storage 价格和用量
  4. 点击以测试模式开始。阅读有关安全规则的免责声明。
    在本 Codelab 的后面部分,您将添加安全规则来保护您的数据。在未为您的存储桶添加安全规则的情况下,请不要公开分发或公开应用。
  5. 点击创建

7. 配置 Web 应用

现在,您已创建 Firebase 项目并启用了应用中使用的所有 Firebase 服务,接下来就可以开始在 IDX 中配置 Web 应用以使用这些服务了。

在 IDX 中登录 Firebase CLI

IDX 已安装 Node.js 和 Firebase CLI,因此您可以跳过安装步骤,直接开始设置 CLI。

  1. 在 IDX 内的终端中,运行以下命令,将 CLI 配置为使用您之前创建的 Firebase 项目:
    firebase login --no-localhost
    firebase use --add
    
    当系统提示输入别名时,输入 codelab
  2. 根据您是否希望 Firebase 收集数据,请输入 YN。这两种方式都适用于此 Codelab。
  3. 在浏览器中,选择您的 Google 账号,然后点击允许

部署安全规则和索引

您复制到 GitHub 代码库中的代码已经为 Firestore(位于 firestore.rules 中)和 Cloud Storage for Firebase(位于 storage.rules 中)设置了一组安全规则。部署安全规则后,数据库和存储分区中的数据可以得到更好的保护,避免遭到滥用。

您还可以使用 CLI 部署一组 Firestore 索引(位于 firestore.indexes.json 中),以启用高级查询。

  1. 在 IDX 内的终端中,运行以下命令以部署这些安全规则和索引:
    firebase deploy --only firestore,storage
    
  2. 如果系统询问您:"Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?",请按 Enter 选择

将 Firebase 配置添加到 Web 应用代码中

  1. 在 Firebase 控制台中,执行以下操作:
    1. 前往项目设置
    2. 向下滚动到您的应用部分,然后选择与 App Hosting 后端同名的应用。
    3. SDK 设置和配置下,选择配置选项,然后复制 firebaseConfig 变量的属性及其值。
  2. 在 IDX 中,执行以下操作:
    1. 打开 apphosting.yaml 文件。您可以在此处设置 App Hosting 上的环境变量,以及 Secret 和运行时配置。
    2. 使用从 Firebase 控制台复制的配置值填充提供的环境变量值。例如(请替换为您自己的值):
      runConfig:
          minInstances: 0
          maxInstances: 2
      env:
          # Get these values from the Firebase console
          - variable: NEXT_PUBLIC_FIREBASE_API_KEY
              value: xxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxx
          - variable: NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
              value: project-id.firebaseapp.com
          - variable: NEXT_PUBLIC_FIREBASE_PROJECT_ID
              value: project-id
          - variable: NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
              value: project-id.firebasestorage.app
          - variable: NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
              value: 111111111111
          - variable: NEXT_PUBLIC_FIREBASE_APP_ID
              value: 1:111111111111:web:aaaaaaaaaaaaaaaaaaaaaa
      
    3. 保存文件。然后,在 IDX 内的终端中运行以下命令,将更改推送到 GitHub:
      git commit -a -m "Setup Firebase Config"
      
      git push
      
  3. 返回 Firebase 控制台,然后重新前往 App Hosting 页面,接着执行以下操作:
    1. 点击后端对应的查看信息中心
    2. 观察系统是否已通过您的 Git 推送触发新构建!完成构建并部署到 Cloud Run 大约需要 3 分钟。您可以点击 build-ID 信息块来监控其进度。
    3. 刷新控制台页面,查看发布是否已完成。完成后,点击网域下以 .hosted.app 结尾的网域链接,打开并查看新部署的应用!

恭喜,您已部署初始 Web 应用!让我们再深入了解一下。

8. 在浏览器中试用 Web 应用

验证您是否可以使用 Firebase 身份验证功能登录

  1. 在浏览器中,刷新显示 Web 应用的页面。
  2. 点击使用 Google 账号登录 (Sign in with Google)。
  3. 退出并重新登录。该网页会实时更新,且无需刷新网页。您可以针对不同用户重复此步骤。
  4. 可选:在浏览器中,刷新该 Web 应用。右键点击该 Web 应用,选择查看网页源代码,然后搜索显示名称。该名称会在从服务器返回的原始 HTML 源代码中显示。

查看餐厅信息

该 Web 应用包含餐馆和评价的模拟数据

如需将模拟餐厅数据插入 Cloud Firestore 数据库,请依次选择 2cf67d488d8e6332.png > 添加示例餐厅

验证餐馆商家信息是否在服务器运行时加载

使用 Next.js 框架时,在服务器运行时或客户端运行时加载数据的时间可能不明显。

如需验证餐厅商家信息是否在服务器运行时加载,请按以下步骤操作:

  1. 在 Web 应用中,打开开发者工具并停用 JavaScript在开发者工具中停用 JavaScipt
  2. 刷新 Web 应用。餐馆商家信息仍会加载。服务器响应中会返回餐馆信息。当 JavaScript 处于启用状态时,餐厅信息会通过客户端 JavaScript 代码进行水合处理。
  3. 在开发者工具中,重新启用 JavaScript
  4. 在 Web 应用中,选择 27ca5d1e8ed8adfe.png > 添加示例餐馆。如果正确实现快照功能,餐馆会实时显示,而无需刷新网页。

添加对餐厅的评价

如需添加评价并验证其是否已插入 Cloud Firestore,请按以下步骤操作:

  1. 刷新 Web 应用,然后从首页选择一家餐馆。
  2. 在餐厅页面上,点击 3e19beef78bb0d0e.png
  3. 请选择星级评分。
  4. 撰写评价。
  5. 点击提交。您的评价会显示在评价列表的顶部。

9. 利用生成式 AI 总结餐厅评价

在本部分中,您将添加评价摘要功能,以便用户无需阅读每条评价,即可快速了解大家对某家餐厅的看法。

在 Cloud Secret Manager 中存储 Gemini API 密钥

App Hosting 与 Cloud Secret Manager 集成,可让您安全地存储 API 密钥等敏感值。

  1. 如需使用 Gemini API,您需要一个 API 密钥。在 Google AI Studio 中创建密钥
    当系统提示时,选择您一直用于此 Codelab 的同一项目(从本质上讲,Firebase 项目就是 Google Cloud 项目)。
  2. 在 IDX 内的终端中,运行以下命令以创建新的 Secret:
    firebase apphosting:secrets:set gemini-api-key
    
  3. 当系统提示您输入 Secret 值时,请从 Google AI Studio 复制并粘贴您的 Gemini API 密钥。
  4. 如果系统询问您:"To use this secret, your backend's service account must be granted access. Would you like to grant access now?",请按 Enter 选择
  5. 当系统询问是否应将新 Secret 添加到 apphosting.yaml 时,输入 Y 以接受,然后按 Enter 选择 GEMINI_API_KEY 作为环境变量名称。

您的 Gemini API 密钥现已安全地存储在 Cloud Secret Manager 中,并且可供 App Hosting 后端访问。您还可以在 Google Cloud 控制台中的 Secrets Manager 信息中心内查看该值。

  1. 打开 apphosting.yaml 文件,并注意,系统已记录您的 Secret 名称,但未记录值。该文件应如下所示:
    runConfig:
        minInstances: 0
        maxInstances: 2
    env:
        # Get these values from the Firebase console
        - variable: NEXT_PUBLIC_FIREBASE_API_KEY
            value: xxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxx
        - variable: NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
            value: project-id.firebaseapp.com
        - variable: NEXT_PUBLIC_FIREBASE_PROJECT_ID
            value: project-id
        - variable: NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
            value: project-id.firebasestorage.app
        - variable: NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
            value: 111111111111
        - variable: NEXT_PUBLIC_FIREBASE_APP_ID
            value: 1:111111111111:web:aaaaaaaaaaaaaaaaaaaaaa
        - variable: GEMINI_API_KEY
            secret: gemini-api-key
    

实现评价摘要组件

  1. 在 IDX 中,打开 src/components/Reviews/ReviewSummary.jsx
  2. 将整个 GeminiSummary 函数替换为以下代码:
    export async function GeminiSummary({ restaurantId }) {
        const { firebaseServerApp } = await getAuthenticatedAppForUser();
        const reviews = await getReviewsByRestaurantId(
            getFirestore(firebaseServerApp),
            restaurantId
        );
    
        const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
        const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash",
        safety_settings: [
            {
            category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
            threshold: HarmBlockThreshold.BLOCK_NONE,
            },
        ],
        });
        const reviewSeparator = "@";
        const prompt = `
            Based on the following restaurant reviews,
            where each review is separated by a '${reviewSeparator}' character,
            create a one-sentence summary of what people think of the restaurant.
    
            Here are the reviews: ${reviews.map(review => review.text).join(reviewSeparator)}
        `;
    
        try {
            const result = await model.generateContent(prompt);
            const response = await result.response;
            const text = response.text();
    
            return (
                <div className="restaurant__review_summary">
                    <p>{text}</p>
                    <p> Summarized with Gemini</p>
                </div>
            );
        } catch (e) {
            console.error(e);
            return <p>Error contacting Gemini</p>;
        }
    }
    
  3. 在 IDX 内的终端中,运行以下命令以创建提交并将其推送到您的 GitHub 代码库。
    git commit -a -m "Use AI to summarize reviews"
    
    git push
    
  4. 在 Firebase 控制台中,打开应用托管页面,然后等待新发布完成。
  5. 在浏览器中,点击餐厅卡片。在屏幕顶部,您应该会看到有关该餐厅的所有评价的简短摘要。
  6. 添加新评价并刷新页面。您应该会看到摘要发生变化。

10. 总结

恭喜!您了解了如何使用 Firebase App Hosting 部署 Next.js 应用,以及如何使用 Gemini API 总结文本。具体来说,您使用了以下内容:

  • Firebase App Hosting,以便在每次推送到配置的 GitHub 分支时自动构建和部署 Next.js 代码。
  • Cloud Secret Manager(与 App Hosting 集成)可用于安全地存储 Gemini API 密钥,以便您在应用中构建生成式 AI 功能。

了解详情

深入了解完整的 Codelab“将 Firebase 与 Next.js 应用集成”,了解我们如何向此应用添加 Firebase Authentication、Cloud Firestore 和 Cloud Storage for Firebase。

此外,您还可以查看更多 Codelab: