Skip to main content

Firebase功能:Functions

步驟 1:設定 Firebase 專案

  1. 建立 Firebase 專案

    • 前往 Firebase 主控台

    • 點擊「新增專案」,輸入專案名稱(例如 my-firebase-app),然後按「繼續」。

    • 選擇是否啟用 Google Player: System: 啟用 Google Analytics(可選,建議關閉以簡化流程)。

    • 點擊「建立專案」,等待 Firebase 完成設定。

  2. 安裝 Firebase CLI
    你需要 Firebase CLI 來初始化和部署 Cloud Functions。執行以下指令以全局安裝 Firebase CLI:

    npm install -g firebase-tools
  3. 初始化 Firebase
    在你的專案資料夾(my-firebase-app)中,執行以下指令:

    firebase login

    這會要求你使用 Google 帳戶登入 Firebase CLI。接著執行:

    firebase init
    • 在初始化選項中,選擇 Functions(Cloud Functions) 和 Hosting(用於部署前端)。

    • 選擇「Use an existing project」,然後選取你剛剛建立的 Firebase 專案。

    • 當提示「What do you want to use as your public directory?」時,輸入 dist(Vite 建置後的輸出資料夾)。

    • 選擇 JavaScript 作為 Cloud Functions 的語言(本教學使用 JavaScript)。

    • 選擇是否安裝依賴(建議選擇 Yes,讓 CLI 自動安裝 firebase-functions 和 firebase-admin)。

    初始化完成後,你的專案資料夾會包含一個 functions 資料夾,裡面有預設的 Cloud Functions 範例程式碼。

  4. 新增 Firebase SDK 到 React 專案
    在 my-firebase-app 資料夾中,安裝 Firebase SDK:

    npm install firebase
  5. 設定 Firebase 配置

    • 在 Firebase 主控台中,點擊「新增應用程式」並選擇「網頁應用程式」。

    • 複製提供的 Firebase 配置物件(firebaseConfig)。

    • 在專案根目錄中建立一個 .env 檔案,用於儲存 Firebase 配置。範例:

      VITE_FIREBASE_API_KEY=your_api_key
      VITE_FIREBASE_AUTH_DOMAIN=your-auth-domain
      VITE_FIREBASE_PROJECT_ID=your-project_id
      VITE_FIREBASE_STORAGE_BUCKET=your_storage_bucket
      VITE_FIREBASE_MESSAGING_SENDER_ID=your-message-sender-id
      VITE_FIREBASE_APP_ID=your-firebase-id
    • 建立一個 src/firebase.js 檔案,用於初始化 Firebase:

      // src/firebase.js
      import { initializeApp } from 'firebase/app';
      import { getFunctions } from 'firebase/functions';

      const firebaseConfig = {
      apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
      authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
      projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
      storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
      messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
      appId: import.meta.env.VITE_FIREBASE_APP_ID,
      };

      const app = initializeApp(firebaseConfig);
      const functions = getFunctions(app);

      export { functions };

    這個檔案初始化 Firebase 並導出 functions,供前端呼叫 Cloud Functions 使用。


步驟 2:撰寫 Firebase Cloud Functions

  1. 進入 functions 資料夾
    進入專案根目錄中的 functions 資料夾,找到 index.js 檔案,這是 Cloud Functions 的主要檔案。

  2. 撰寫一個簡單的 Cloud Function
    編輯 functions/index.js,加入一個簡單的 HTTP 觸發的 Cloud Function。例如,一個返回問候訊息的函數:

    // functions/index.js
    const functions = require('firebase-functions');

    exports.helloWorld = functions.https.onRequest((request, response) => {
    response.send('Hello from Firebase Cloud Functions!');
    });

    這段程式碼定義了一個名為 helloWorld 的 HTTP 函數,當前端呼叫時會返回一個簡單的文字訊息。

  3. 部署 Cloud Functions
    在專案根目錄中執行以下指令,部署 Cloud Functions:

    firebase deploy --only functions

    部署完成後,Firebase CLI 會提供一個 URL,例如 https://us-central1-your-project-id.cloudfunctions.net/helloWorld ,你可以用這個 URL 來呼叫你的函數。


步驟 4:在 React 專案中呼叫 Cloud Functions

  1. 建立一個元件來呼叫 Cloud Function
    在 src/App.jsx 中,撰寫一個簡單的 React 元件來呼叫 helloWorld 函數:

    // src/App.jsx
    import { useState } from 'react';
    import { httpsCallable } from 'firebase/functions';
    import { functions } from './firebase';

    function App() {
    const [message, setMessage] = useState('');

    const callHelloWorld = async () => {
    try {
    const helloWorld = httpsCallable(functions, 'helloWorld');
    const result = await helloWorld();
    setMessage(result.data);
    } catch (error) {
    console.error('Error calling Cloud Function:', error);
    setMessage('Error occurred');
    }
    };

    return (
    <div>
    <h1>Firebase Cloud Functions 測試</h1>
    <button onClick={callHelloWorld}>呼叫 Cloud Function</button>
    <p>回應: {message}</p>
    </div>
    );
    }

    export default App;
    • 這段程式碼使用 httpsCallable 來呼叫 helloWorld 函數,並將回應顯示在頁面上。

    • 注意:你需要從 firebase.js 導入 functions。

  2. 測試前端呼叫
    執行 npm run dev 啟動 Vite 開發伺服器,然後在瀏覽器中點擊按鈕,應該會看到來自 Cloud Function 的回應「Hello from Firebase Cloud Functions!」。


步驟 3:部署 Vite + React 專案到 Firebase Hosting

  1. 建置 Vite 專案
    執行以下指令,建置專案並生成 dist 資料夾:

    npm run build
  2. 部署到 Firebase Hosting
    執行以下指令,將前端應用程式部署到 Firebase Hosting:

    firebase deploy --only hosting

    部署完成後,Firebase CLI 會提供一個 Hosting URL(例如 https://your-project-id.web.app ),你可以在瀏覽器中訪問你的應用程式。


常見問題與解決方案

  1. 錯誤:Firebase: No Firebase App '[DEFAULT]' has been created

    • 確保 src/firebase.js 正確初始化 Firebase,並且 .env 檔案中的環境變數正確。

    • 檢查 .env 檔案中的鍵名是否以 VITE_ 開頭(Vite 的環境變數要求如此)。

  2. Cloud Functions 無法呼叫

    • 確認你的 Cloud Functions 已成功部署(使用 firebase deploy --only functions)。

    • 檢查 Firebase 主控台中的 Functions 標籤,確保函數名稱正確。

    • 確保你的專案已啟用 Blaze 定價計劃(Cloud Functions 需要 Blaze 計劃)。

  3. CORS 問題
    如果直接使用 fetch 呼叫 Cloud Functions 的 URL,可能會遇到 CORS 問題。建議使用 Firebase SDK 的 httpsCallable,因為它會自動處理 CORS。


進階:撰寫更複雜的 Cloud Functions

以下是一個更實用的 Cloud Function 範例,用於處理前端傳來的資料並儲存到 Firestore:

  1. 初始化 Firestore
    在 functions/index.js 中,初始化 Firestore:

    // functions/index.js
    const functions = require('firebase-functions');
    const admin = require('firebase-admin');

    admin.initializeApp();

    exports.addMessage = functions.https.onCall((data, context) => {
    const { text } = data;
    if (!text) {
    throw new functions.https.HttpsError('invalid-argument', 'Text is required');
    }

    return admin.firestore().collection('messages').add({
    text,
    createdAt: admin.firestore.FieldValue.serverTimestamp(),
    }).then(() => {
    return { message: 'Message added successfully' };
    }).catch(error => {
    throw new functions.https.HttpsError('internal', 'Error adding message');
    });
    });
    • 這個 addMessage 函數接受前端傳來的 text 資料,並將其儲存到 Firestore 的 messages 集合中。

    • 注意:這是一個 Callable Function,使用 onCall 而不是 onRequest,因為它支援前端直接呼叫並提供身份驗證支援。

  2. 在 React 中呼叫 Callable Function
    修改 src/App.jsx:

    // src/App.jsx
    import { useState } from 'react';
    import { httpsCallable } from 'firebase/functions';
    import { functions } from './firebase';

    function App() {
    const [message, setMessage] = useState('');
    const [response, setResponse] = useState('');

    const addMessage = async () => {
    try {
    const addMessageFunction = httpsCallable(functions, 'addMessage');
    const result = await addMessageFunction({ text: message });
    setResponse(result.data.message);
    setMessage('');
    } catch (error) {
    console.error('Error calling Cloud Function:', error);
    setResponse('Error occurred');
    }
    };

    return (
    <div>
    <h1>Firebase Cloud Functions 測試</h1>
    <input
    type="text"
    value={message}
    onChange={(e) => setMessage(e.target.value)}
    placeholder="輸入訊息"
    />
    <button onClick={addMessage}>新增訊息</button>
    <p>回應: {response}</p>
    </div>
    );
    }

    export default App;
  3. 部署並測試

    • 重新部署 Cloud Functions:

      firebase deploy --only functions
    • 執行 npm run dev,在瀏覽器中輸入文字並點擊按鈕,檢查 Firestore 的 messages 集合是否新增了資料。