使用 Next.js 應用程式部署至 Firebase App Hosting

1. 事前準備

在本程式碼研究室中,您將使用名為 Friendly Eats 的 Next.js 網頁應用程式 (餐廳評論網站),瞭解如何部署至 Firebase App Hosting。

Friendly Eats 網頁應用程式

完成的網頁應用程式提供實用功能,可展示 Firebase 如何協助您建構 Next.js 應用程式。

  • 自動建構及部署:本程式碼研究室會說明如何使用 Firebase 應用程式託管,在每次推送至已設定的分支時,自動建構及部署 Next.js 程式碼。
  • 登入和登出:完成的網頁應用程式可讓使用者透過 Google 登入/登出。使用者登入和持續性完全透過 Firebase 驗證管理。
  • 圖片:完成的網頁應用程式可讓登入的使用者上傳餐廳圖片。圖片資產會儲存在 Cloud Storage for Firebase。Firebase JavaScript SDK 會提供上傳圖片的公開網址。接著,這個公開網址會儲存在 Cloud Firestore 中相關的餐廳文件中。
  • 篩選器:完成的網頁應用程式可讓登入的使用者依類別、地點和價格篩選餐廳清單。您也可以自訂使用的排序方式。系統會從 Cloud Firestore 存取資料,並根據所用的篩選條件套用 Firestore 查詢。
  • 評論:完成的網頁應用程式可讓登入的使用者發布餐廳評論,包括星級評分和文字訊息。評論資訊會儲存在 Cloud Firestore 中。
  • 評論摘要:完成的網頁應用程式會使用 Gemini 模型自動摘要評論。AI 生成摘要會儲存在 Cloud Firestore 中。

事前準備

  • 瞭解 Next.js 和 JavaScript

課程內容

  • 如何搭配 Next.js 應用程式路由器和伺服器端算繪功能使用 Firebase
  • 如何僅使用伺服器端 Secret 授權呼叫 Gemini API

事前準備

  • 你選擇的瀏覽器,例如 Google Chrome
  • 存取 IDX.dev (網頁式工作區)
  • 用於建立及管理 Firebase 專案的 Google 帳戶
  • GitHub 帳戶 (不一定要與上述電子郵件帳戶相同)

2. 設定開發環境和 GitHub 存放區

本程式碼研究室提供應用程式的入門程式碼庫,並使用 Firebase CLI 和 IDX.dev。

建立新的 GitHub 存放區並匯入 IDX

Firebase App Hosting 可讓您設定 GitHub 存放區,以便在每次推送至已設定的分支版本時,建構及部署 Next.js 程式碼。

  1. 為本程式碼研究室建立新的 GitHub 存放區:https://github.com/new。您可以將其命名為任何名稱,例如 MyFriendlyEatsCodelab
  2. 複製新存放區網址。如下所示:
    https://github.com/USER_NAME/REPOSITORY_NAME.git
  3. 前往 https://idx.google.com 並登入。
  4. 按一下「Import a repo」(匯入存放區),然後貼上複製的 GitHub 網址。
    IDX 會提示您連結至 GitHub,然後複製 (空白) 存放區。

查看程式碼研究室的原始碼存放區

如要查看程式碼研究室來源,請前往 https://github.com/firebase/friendlyeats-webfriendlyeats-web 存放區包含多個平台的範例專案。

您目前進行的程式碼研究室只著重於 Firebase App Hosting 和 Gemini API,是完整程式碼研究室「整合 Firebase 與 Next.js 應用程式」的簡短版本。這個簡短的程式碼研究室要求您只能使用 friendlyeats-web 存放區 #io-connect 分支中的原始碼,特別是 nextjs-step10 目錄。

請注意 friendlyeats-web 存放區的下列其他目錄。即使本程式碼研究室不需要這些目錄,瞭解這些目錄仍有助於您學習。

將程式碼研究室來源複製到新存放區

以下說明如何將 nextjs-step10 目錄複製到自己的存放區:

  1. 在 IDX 中,依序點選「Menu」>「Terminal」>「New Terminal」,開啟終端機。
  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. 查看範例程式碼集

在本節中,您將查看應用程式的入門程式碼庫,並在本程式碼研究室中新增功能。

資料夾和檔案結構

下表概略說明應用程式的資料夾和檔案結構:

資料夾和檔案

說明

src/components

篩選器、標題、餐廳詳細資料和評論的 React 元件

src/lib

不一定會繫結至 React 或 Next.js 的公用程式函式

src/lib/firebase

Firebase 專屬程式碼和 Firebase 設定

public

網頁應用程式中的靜態資產,例如圖示

src/app

使用 Next.js 應用程式路由器進行轉送

src/app/restaurant

API 路由處理常式

package.jsonpackage-lock.json

使用 npm 管理專案依附元件

next.config.js

Next.js 專屬設定 (啟用伺服器動作)

jsconfig.json

JavaScript 語言服務設定

伺服器和用戶端元件

這個應用程式是使用 App Router 的 Next.js 網頁應用程式。應用程式會使用伺服器轉譯功能。舉例來說,src/app/page.js 檔案是負責主要網頁的伺服器元件。src/components/RestaurantListings.jsx 檔案是用戶端元件,檔案開頭會以 "use client" 指令表示。

匯入陳述式

在某些檔案中,您可能會看到類似下列的匯入陳述式:

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

應用程式使用 @ 符號,避免使用笨拙的相對匯入路徑,而這一切都是 路徑別名的功勞。

Firebase 專屬 API

所有 Firebase API 程式碼都包裝在 src/lib/firebase 目錄中。然後,個別 React 元件會從 src/lib/firebase 目錄匯入包裝函式,而不是直接匯入 Firebase 函式。

模擬資料

模擬餐廳和評論資料位於 src/lib/randomData.js 檔案中。該檔案的資料會組裝在 src/lib/fakeRestaurants.js 檔案的程式碼中。

4. 設定 Firebase 專案

在本節中,您將設定 Firebase 專案,並將 Firebase 網頁應用程式與該專案建立關聯。您也會設定範例網頁應用程式使用的 Firebase 服務。

建立 Firebase 專案

  1. 使用上一個步驟中使用的 Google 帳戶登入 Firebase 控制台
  2. 按一下按鈕建立新專案,然後輸入專案名稱 (例如 FriendlyEats Codelab)。
  3. 按一下「繼續」
  4. 如果系統提示,請詳閱並接受 Firebase 條款,然後按一下「繼續」
  5. (選用) 在 Firebase 控制台中啟用 AI 輔助功能 (稱為「Gemini in Firebase」)。
  6. 本程式碼研究室不需要 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 帳戶的資格。
  • 如果您是在活動中進行這項程式碼研究室,請詢問主辦單位是否有可用的 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 頁面應用程式代管控制台的零狀態,並顯示「開始使用」按鈕
  2. 按一下「開始使用」,即可開始建立後端。
  3. 按照提示匯入並連結您先前建立的 GitHub 存放區。
  4. 設定部署設定:
    • 將根目錄保留為 /
    • 將即時分支設為 main
    • 啟用自動推出功能
  5. 為後端命名 friendlyeats-codelab (或選擇後端名稱)。這會成為用來存取後端的網域一部分。
    這個工作流程也會在 Firebase 專案中自動建立 Firebase 網頁應用程式。在本程式碼研究室的後續步驟中,您會使用這個網頁應用程式的設定值,將程式碼集連結至 Firebase 專案。
  6. 按一下「完成並部署」。稍待片刻,系統會將您帶往新頁面,您可以在該頁面查看新 App Hosting 後端的狀態!
  7. 從 App Hosting 資訊主頁複製新網域。
    網域的模式會類似 BACKEND_ID--PROJECT_ID.REGION.hosted.app。稍後設定 Firebase 驗證時,會用到這個網域。

由於 DNS 傳播和 SSL 憑證建立作業需要時間,網域可能要過幾分鐘才會開始運作。後端建立完成前,請繼續設定其餘 Firebase 專案,並設定後端 (本程式碼實驗室的後續步驟)。

每當您將新的修訂版本推送至 GitHub 存放區的 main 分支版本時,Firebase 主控台就會開始新的建構和推出作業,並在推出作業完成後自動更新網站。

6. 設定其他 Firebase 服務

雖然本程式碼研究室只著重於 Firebase 應用程式代管和 Gemini API,但運作中的網頁應用程式需要其他 Firebase 服務才能運作。讓所有這些服務在應用程式中運作的程式碼,都屬於您複製到自己 GitHub 存放區的程式碼集,但您仍需在 Firebase 專案中設定這些服務。

設定驗證

  1. 在 Firebase 控制台中,前往「驗證」
  2. 按一下「開始使用」
  3. 在「其他供應商」欄中,依序點選「Google」>「啟用」
    1. 在「專案的公開名稱」文字方塊中輸入名稱,例如 My FriendlyEatsCodelab app
    2. 從「專案的支援電子郵件地址」下拉式選單中,選取您的電子郵件地址。
    3. 按一下 [儲存]
  4. 在「驗證」頁面中,按一下「設定」分頁標籤。
    1. 按一下畫面左側選單中的「授權網域」
    2. 按一下「新增網域」,然後新增新建立的 App Hosting 網域 (結尾為 .hosted.app)。
    3. 按一下「新增」儲存設定。

設定 Cloud Firestore

  1. 在 Firebase 控制台的左側面板中,展開「Build」,然後選取「Firestore database」
  2. 按一下 [Create database] (建立資料庫)。
  3. 將「資料庫 ID」保留為 (default)
  4. 選取資料庫位置,然後按一下「下一步」
    如果是實際應用程式,請選擇離使用者較近的位置。
  5. 按一下「以測試模式啟動」。請詳閱安全性規則免責事項。
    在本程式碼研究室的後續步驟中,您將新增安全性規則,確保資料安全。請勿在未為資料庫新增安全性規則的情況下,公開發布或公開應用程式。
  6. 點選「建立」

設定 Cloud Storage for Firebase

  1. 在 Firebase 主控台的左側面板中,展開「Build」,然後選取「Storage」
  2. 按一下「開始使用」
  3. 選取預設 Storage bucket 的位置。
    位於 US-WEST1US-CENTRAL1US-EAST1 的 bucket 可享有 Google Cloud Storage 的「永久免費」方案。其他所有位置的值區均適用 Google Cloud Storage 定價和用量
  4. 按一下「以測試模式啟動」。請詳閱安全性規則免責事項。
    在本程式碼研究室的後續步驟中,您將新增安全性規則來保護資料。請勿在未為 Storage 值區新增安全規則的情況下,公開發布或公開應用程式。
  5. 點選「建立」

7. 設定 Web 應用程式

您已建立 Firebase 專案,並啟用應用程式中使用的所有 Firebase 服務,現在可以開始在 IDX 中設定網路應用程式,以便使用這些服務。

在 IDX 中登入 Firebase CLI

IDX 已安裝 Node.js 和 Firebase CLI,因此您可以略過安裝步驟,直接開始設定 CLI。

  1. 在 IDX 的終端機中執行下列指令,設定 CLI 以使用您先前建立的 Firebase 專案:
    firebase login --no-localhost
    firebase use --add
    
    系統提示輸入別名時,請輸入 codelab
  2. 視是否要讓 Firebase 收集資料,輸入 YN。這兩個選項都適用於本程式碼研究室。
  3. 在瀏覽器中選取 Google 帳戶,然後按一下「允許」

部署安全性規則和索引

您複製到 GitHub 存放區的程式碼,已包含 Firestore (位於 firestore.rules) 和 Firebase 適用的 Cloud Storage (位於 storage.rules) 的安全規則集。部署安全規則後,資料庫和 bucket 中的資料就能受到更完善的保護,避免遭到濫用。

您也可以使用 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 設定新增至網頁應用程式程式碼

  1. 在 Firebase 控制台中,請執行下列步驟:
    1. 前往「專案設定」
    2. 向下捲動至「你的應用程式」部分,然後選取與 App Hosting 後端同名的應用程式。
    3. 在「SDK setup and configuration」(SDK 設定和設定) 下方,選擇「Config」(設定) 選項,然後複製 firebaseConfig 變數的屬性和值。
  2. 在 IDX 中執行下列操作:
    1. 開啟 apphosting.yaml 檔案,您可以在這裡設定 App Hosting 的環境變數,以及密鑰和執行階段設定。
    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. 重新整理控制台頁面,確認推出作業是否完成。完成後,請點選「domains」下方的網域連結 (結尾為 .hosted.app),開啟並查看新部署的應用程式!

恭喜,您已部署初始網頁應用程式!讓我們再深入瞭解。

8. 在瀏覽器中試用網頁應用程式

確認您可以使用 Firebase 驗證登入

  1. 在瀏覽器中,重新整理顯示網頁應用程式的頁面。
  2. 點選 [Sign in with Google] (使用 Google 帳戶登入)
  3. 登出後再次登入,頁面會即時更新,不必重新整理。你可以對不同使用者重複這個步驟。
  4. 選用:在瀏覽器中重新整理網頁應用程式。在網頁應用程式上按一下滑鼠右鍵,選取「檢視網頁原始碼」,然後搜尋顯示名稱。這會顯示在伺服器傳回的原始 HTML 來源中。

查看餐廳資訊

網頁應用程式包含餐廳和評論的模擬資料

如要將模擬餐廳資料插入 Cloud Firestore 資料庫,請選取 2cf67d488d8e6332.png>「新增範例餐廳」

確認餐廳資訊會在伺服器執行階段載入

使用 Next.js 架構時,您可能無法清楚瞭解資料是在伺服器執行階段或用戶端執行階段載入。

如要確認餐廳商家資訊是否在伺服器執行階段載入,請按照下列步驟操作:

  1. 在網頁應用程式中開啟開發人員工具,然後停用 JavaScript在開發人員工具中停用 JavaScript
  2. 重新整理網頁應用程式。餐廳資訊仍會載入。伺服器回應會傳回餐廳資訊。啟用 JavaScript 後,系統會透過用戶端 JavaScript 程式碼補水餐廳資訊。
  3. 在開發人員工具中重新啟用 JavaScript
  4. 在網頁應用程式中,依序選取 27ca5d1e8ed8adfe.png>「新增範例餐廳」。如果快照函式實作正確,餐廳就會即時顯示,不需重新整理頁面。

新增餐廳評論

如要新增評論並確認評論已插入 Cloud Firestore,請按照下列步驟操作:

  1. 重新整理網頁應用程式,然後從首頁選取餐廳。
  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 中建立金鑰
    系統提示時,請選取您用於本程式碼研究室的專案 (在幕後,Firebase 專案就是 Google Cloud 專案)。
  2. 在 IDX 的終端機中執行下列指令,建立新的密鑰:
    firebase apphosting:secrets:set gemini-api-key
    
  3. 系統提示輸入密鑰值時,請從 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. 系統詢問是否要將新密鑰新增至 apphosting.yaml 時,請輸入 Y 接受,然後按下 Enter 選取 GEMINI_API_KEY 做為環境變數名稱。

Gemini API 金鑰現在已安全地儲存在 Cloud Secret Manager 中,且可供 App Hosting 後端存取。您也可以在 Google Cloud Console 的 Secrets Manager 資訊主頁中查看這個值。

  1. 開啟 apphosting.yaml 檔案,並注意系統已記錄密鑰名稱,但未記錄值。檔案內容應如下所示:
    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 控制台中開啟 App Hosting 頁面,等待新的推出作業完成。
  5. 在瀏覽器中按一下餐廳資訊卡。畫面頂端會顯示餐廳所有評論的摘要 (一句話)。
  6. 新增評論並重新整理頁面。您應該會看到摘要變更。

10. 結論

恭喜!您學會了如何使用 Firebase App Hosting 部署 Next.js 應用程式,以及如何使用 Gemini API 摘要文字。具體來說,您使用了下列項目:

  • Firebase 應用程式代管:每當您將程式碼推送至已設定的 GitHub 分支版本時,系統會自動建構及部署 Next.js 程式碼。
  • Cloud Secret Manager (與 App Hosting 整合) 可安全地儲存 Gemini API 金鑰,方便您在應用程式中建構生成式 AI 功能。

瞭解詳情

請參閱完整的「將 Firebase 與 Next.js 應用程式整合」程式碼實驗室,瞭解我們如何將 Firebase 驗證、Cloud Firestore 和 Cloud Storage for Firebase 新增至這個應用程式。

此外,請參閱更多程式碼研究室: