跳至主要内容

2 篇文章 含有標籤「React Redux」

檢視所有標籤

Backend For Frontend(BFF)入門教學筆記 | 學習筆記

· 閱讀時間約 5 分鐘
kdchang

前言

當今前端與後端開發越趨分離,加上行動裝置、多樣化的使用者端(Web、App、IoT 等)快速成長,Backend for Frontend(BFF) 架構逐漸成為微服務與現代應用中不可或缺的一環。本文將介紹 BFF 的基本概念、優缺點、使用情境與實際範例,幫助你快速理解並在專案中應用。

一、什麼是 Backend For Frontend?

Backend For Frontend(簡稱 BFF) 是一種後端架構模式,其核心理念是:每種前端應用(Web、Mobile App、Smart TV)都由各自專屬的後端服務來支援,這個後端只為對應的前端量身打造。

傳統系統中,前端直接呼叫後端 API 或微服務,常會遇到以下問題:

  • 回傳資料過多(浪費頻寬)
  • 回傳資料不夠(還要多次請求)
  • 錯誤格式(不適合前端解析)
  • 缺乏聚合邏輯(需要組裝多個 API 回應)

BFF 則專門為特定前端處理這些問題,讓資料更適合顯示、傳輸與渲染,減少耦合與重複工作。


二、BFF 架構示意圖

          +---------------+          +-------------------+
Web App → | BFF for Web | → REST | User Service |
+---------------+ +-------------------+

+----------------+ | REST / RPC
Mobile → | BFF for Mobile | → GraphQL| Order Service |
+----------------+ |

Product Service

每一個 BFF 可以:

  • 聚合多個微服務的資料
  • 轉換資料格式供前端使用
  • 處理權限與驗證邏輯(例如 token 驗證)
  • 實作快取策略(如 CDN, Redis)
  • 提供更穩定的 API 給前端

三、什麼情況適合使用 BFF?

  1. 有多種前端平台:Web 和 App 須分別調整 API。
  2. 資料需聚合多個來源:例如組合訂單資料與商品詳細資訊。
  3. 前端需要特別的資料結構或格式轉換
  4. 希望讓前端開發獨立部署、測試、開發
  5. 希望簡化前端邏輯,把複雜邏輯搬到後端處理

四、BFF 優點與缺點

優點

  • 前後端明確分工,降低耦合
  • 加快前端開發速度
  • 可根據裝置特性量身打造 API
  • 改善效能(避免多餘資料,提升快取)
  • 更容易實施權限控管與安全策略

缺點

  • 增加部署與維護成本(每個前端都需對應 BFF)
  • 需要資源維護 BFF 團隊
  • 需協調不同 BFF 的資料一致性與邏輯重複問題

五、實際範例:Node.js 建立一個 BFF

假設有以下微服務:

  • GET /users/:id 回傳使用者資料
  • GET /orders/user/:id 回傳該用戶的訂單清單

現在我們為 Web 建立一個 BFF,統一提供 /profile/:id 接口,回傳使用者基本資訊與訂單清單。

BFF 架構(Node.js + Express)

// bff/web-server.js
const express = require('express');
const axios = require('axios');
const app = express();

app.get('/profile/:id', async (req, res) => {
const userId = req.params.id;

try {
const [userRes, ordersRes] = await Promise.all([
axios.get(`http://users-service/users/${userId}`),
axios.get(`http://orders-service/orders/user/${userId}`)
]);

res.json({
user: userRes.data,
orders: ordersRes.data
});
} catch (error) {
console.error(error);
res.status(500).send('資料取得失敗');
}
});

app.listen(3000, () => {
console.log('BFF for Web running at http://localhost:3000');
});

使用說明

  • 前端只需呼叫 GET /profile/123 即可拿到整合後的資料。
  • BFF 內部負責跟不同服務串接、組裝、錯誤處理與轉換格式。

六、BFF 和 GraphQL 的關係

GraphQL 本身也常用於 BFF 的實作方式之一。透過 GraphQL:

  • 前端可以自己定義要的欄位(防止 over-fetch)
  • 可以統一查詢不同來源資料(類似 BFF 的聚合邏輯)
  • 可搭配 Apollo Server 快速搭建

BFF 可以使用 REST,也可以使用 GraphQL,取決於前後端的需求與團隊熟悉度。


七、延伸應用:BFF 搭配微前端(Micro Frontend)

當前端本身也是多團隊分工、模組化(例如大型企業的後台管理系統),BFF 可以依照模組拆分,例如:

  • Order 模組對應一個 BFF
  • Admin 模組對應另一個 BFF

讓後端資料與前端 UI 模組相對應,利於組織協作與部署。


八、總結

面向傳統 APIBFF 架構
資料格式後端決定針對前端定製
跨平台支援不佳良好
前端彈性
擴充性
成本中~高(需維護 BFF)

BFF 並不是萬靈丹,但在多平台、多樣前端需求的專案中,非常實用,能夠有效地降低溝通成本、提升開發效率,並提供更佳的 API 使用體驗。

如果你的團隊正在建構大型應用系統,或前端開發頻繁改動,不妨考慮導入 BFF 架構,讓前後端協作更流暢、更可維護。

參考文件

  1. Backend For Frontend 前端模式的後端
  2. 前端開發者該負責寫 API Endpoints 嗎?The Backend For Frontend Pattern (BFF) In Microservices World
  3. Backends for Frontends pattern
  4. Backend for frontend (BFF) pattern— why do you need to know it?

React Redux 介紹入門教學筆記 | 學習筆記

· 閱讀時間約 4 分鐘
kdchang

1. 什麼是 Redux?

Redux 是 JavaScript 應用程式的狀態管理工具,最常與 React 搭配使用。它提供一個單一的全域狀態樹,使應用程式的狀態變更更可預測、可測試、可維護。Redux 遵循 單向數據流不可變狀態 的概念,適合管理大型應用的複雜狀態。


2. Redux 核心概念

Redux 的運作基礎主要由三個部分組成:

  1. Store(存儲狀態的地方)
    • 整個應用程式的狀態存儲在單一的 Store 中。
  2. Action(動作)
    • Action 是一個 JavaScript 物件,描述了「發生了什麼事」。通常包含 type 屬性來表明事件類型,並可能包含 payload 傳遞額外數據。
  3. Reducer(狀態變更邏輯)
    • Reducer 是一個純函式,接收當前狀態與 Action,根據 Action 類型來決定如何更新狀態。

3. 安裝 Redux 和 React-Redux

在 React 專案中安裝 Redux 及 React-Redux:

npm install @reduxjs/toolkit react-redux

Redux Toolkit(RTK)是官方推薦的 Redux 工具包,它提供更簡潔、易用的 API 來簡化 Redux 使用。


4. 創建 Redux Store

store.js 檔案中,使用 configureStore 創建 Store:

import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./counterSlice";

const store = configureStore({
reducer: {
counter: counterReducer,
},
});

export default store;

在這裡,我們將 counterReducer 設定為 counter 這個 slice 的 reducer。


5. 創建 Slice(Reducer + Action)

counterSlice.js 檔案中,使用 createSlice 定義 counter 相關的狀態與 reducer:

import { createSlice } from "@reduxjs/toolkit";

const counterSlice = createSlice({
name: "counter",
initialState: { value: 0 },
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;

這裡的 createSlice 幫助我們:

  • 定義狀態的初始值(initialState
  • 自動生成 reducer
  • 自動產生對應的 Action

6. 設置 Store 提供給 React

index.js 檔案中使用 Provider 讓整個 React 應用可以存取 Redux Store:

import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import store from "./store";
import App from "./App";

ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);

這樣 App 及其所有子元件都可以存取 Redux Store。


7. 在 React 組件中使用 Redux

Counter.js 中使用 Redux Store 來讀取與修改 counter 的值:

import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { increment, decrement, incrementByAmount } from "./counterSlice";

const Counter = () => {
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();

return (
<div>
<h1>計數器:{count}</h1>
<button onClick={() => dispatch(increment())}>增加</button>
<button onClick={() => dispatch(decrement())}>減少</button>
<button onClick={() => dispatch(incrementByAmount(5))}>增加 5</button>
</div>
);
};

export default Counter;

在這個範例中:

  • useSelector(state => state.counter.value) 取得 Store 內的 counter 值。
  • useDispatch() 取得 Redux 的 dispatch 函式,發送 Action 來更新狀態。
  • 點擊按鈕時,對應的 Action 會發送給 Reducer,修改狀態。

8. 使用 Redux DevTools 進行除錯

Redux Toolkit 內建支援 Redux DevTools,可以在瀏覽器中查看 Redux 狀態變更的歷史紀錄,方便除錯。安裝 Redux DevTools,並開啟瀏覽器的 Redux 分頁來觀察 Action 和 State 變化。


9. 總結

Redux 提供了一個強大的狀態管理方式,適合中大型應用。在 Redux Toolkit 的幫助下,開發 Redux 應用變得更加直觀與簡潔。本篇介紹了 Redux 的基本概念,並透過實際範例展示如何在 React 中整合 Redux。如果你的應用狀態複雜,需要跨組件共享,Redux 會是很好的選擇。

參考文件

  1. redux vs useContext, useReducer,該怎麼選擇?
  2. The Problem with React's Context API
  3. React 狀態管理套件比較與原理實現 feat. Redux, Zustand, Jotai, Recoil, MobX, Valtio
  4. 利用 React Context API + useReducer 實作 Redux