前端BFF层入门:为什么你的项目需要这样一个中间层

by JeariCk 2 min read
使用node.js搭建前端BFF层

BFF 是什么

BFF 全称 Backend For Frontend,为前端而生的后端。这个模式是 Sam Newman 在 2015 年左右提出来的。核心思想挺直接的:不为所有前端客户端搞一个通用的后端 API,而是为每一种用户体验创建专属的后端服务。

说白了就是在前端和后端之间加一层翻译官。它知道你前端长什么样、需要什么数据、什么时候要,然后去后端帮你拼好再送回来。

使用node.js搭建前端BFF层
使用node.js搭建前端BFF层

为什么会有 前端BFF 这个层

回想一下几年前的一个典型场景:公司最初只有一个 PC 端网页,后端 API 全是给网页量身定做的。后来移动端来了,iOS 和 Android 两个 App 都要上。

问题跟着就来了。移动端屏幕小,展示不了 PC 端那么多信息,需要的数据量完全不是一回事。移动端还得考虑省电、省流量、省带宽——PC 端无所谓的东西到了手机上全成了问题。

功能本身也可能不一样。PC 端你可能慢慢浏览下单,移动端可能更需要扫码比价、店内导航这类场景。后端如果只有一个通用 API,要么不断膨胀满足所有客户端的差异化需求,要么变成团队间的瓶颈——改个接口要排队等排期。

BFF模式就是这时候派上用场的。


BFF 的核心原则

Sam Newman 原文里有个说法我特别认同:一个 BFF 服务应该是”one experience, one BFF”。什么意思?一段用户体验,对应一个 BFF 服务。

比如做电商:
– 桌面端是一个 BFF
– iOS App 是一个 BFF
– Android App 是一个 BFF

每个 BFF 只为它对应的前端服务,数据格式、接口数量、聚合逻辑全由前端的实际需求驱动。不会出现”Android 发了新功能,为啥 iOS 的接口也得跟着改”这种破事。

如果要再严一点,SoundCloud 的做法是 iOS 和 Android 共用一个移动端 BFF,但桌面端单独一个。问题在于如果 iOS 和 Android 的体验差异比较大,共用一个 BFF 反而容易互相拖累。

结论是按团队分更合理。如果 iOS 和 Android 是一个团队维护,共用一个 BFF 问题不大。如果是两个独立团队,最好各用各的。


BFF 到底做什么

1. 数据聚合

微服务架构下,前端一个页面展示的数据可能要跨好几个服务。拿商品详情页来说——商品信息查商品服务,库存查库存服务,价格查价格服务,推荐查推荐服务。

没有 BFF 的话,前端得发 4 个请求,自己拼数据。有了 BFF,前端只发 1 个请求,BFF 帮你并行查 4 个下游服务,拼好了再返回来。

2. 数据裁剪

同样的用户信息,桌面端的列表页需要 name、email、avatar、role,移动端的列表页只想要 name 和 avatar。BFF 可以针对性地做裁剪,不给移动端喂不需要的数据。

3. 协议转换

下游可能是 gRPC、SOAP,甚至老旧的 XML 接口,BFF 可以统一转成前端友好的 JSON REST 或 GraphQL 端点。前端根本不用关心后端用了什么协议。

4. 认证和会话管理

BFF 可以作为认证网关,统一处理登录、Token 刷新、权限校验。前端拿到的就是已经洗干净的数据。


前端BFF 和 API Gateway 有什么区别

这是问得最多的问题。放在一起看就清楚了:

维度API GatewayBFF
定位通用路由网关前端专用后端
受众所有客户端特定的前端体验
职责路由、限流、认证、日志数据聚合、裁剪、UI 适配
团队维护基础设施团队前端团队
代码规模配置驱动,比较通用和前端紧密耦合

实际生产里 API Gateway 和 BFF 往往是前后串联的关系:先过 Gateway(限流、认证),再到 BFF(聚合数据),再到下游微服务。BFF 不是要取代 Gateway,它们解决的是不同层次的问题。


Node.js 在前端BFF 中的角色

前端团队最熟悉的语言是什么?JavaScript、TypeScript。BFF 用 Node.js 写,前端团队自己维护,省去了跨团队的沟通成本。这就是为什么很多前端 BFF 实践都选了 Node.js。

常用的框架:
Next.js API Routes / Server Actions — 如果你在用 React,这可能是最自然的 BFF 方案
NestJS — TypeScript 全栈框架,适合更重一点的 BFF
Express / Fastify — 轻量灵活,自己搭

举个 Express 的例子感受一下:

```javascript
 // BFF 服务:合并商品详情
 app.get('/api/product/:id', async (req, res) => {
 const [product, stock, price] = await Promise.all([
 fetch(`http://product-service/products/${req.params.id}`),
 fetch(`http://inventory-service/stock/${req.params.id}`),
 fetch(`http://pricing-service/price/${req.params.id}`),
 ]);

  const data = {

    ...(await product.json()),

    stock: (await stock.json()).quantity,

    price: (await price.json()).amount,

  };

  // 移动端不需要那么多字段

  if (req.headers['x-client'] === 'mobile') {

    delete data.description;

    delete data.specs;

  }

res.json(data);
 });
 ```


BFF 的常见坑

1. 变成了”胖中间层”

BFF 本意是薄薄的一层。但如果放了太多业务逻辑进去,就会退化成又一个单点瓶颈。BFF 只该做和数据呈现、端侧适配相关的逻辑,业务规则不要往里放。

2. 引入额外延迟

多加一层就多一次网络跳转。数据聚合时如果不注意并行请求,串行调用累积起来,前端感受很明显。尽量用 Promise.all 并行拉取下游数据。

3. 团队职责不清

如果 BFF 还在后端团队手里维护,那基本白搭。BFF 的精髓是由前端团队自己维护、按前端节奏发版——我为我自己的用户体验负责。如果前端改个展示字段还得排后端的队,BFF 就没意义了。

4. 过度设计

一个简单的 CRUD 管理后台,或者只有一个前端客户端,不需要 BFF。加一层没有收益,反而多了维护成本。BFF 适用于多客户端、数据来源分散的场景,不要上来就套。


什么时候该考虑 BFF

结合 Sam Newman 原文和微软 Azure 架构指南:

适合的:
– 多个前端客户端(Web、iOS、Android)需求有明显差异
– 后端是微服务架构,数据来源分散
– 前端团队想要掌控自己的 API 节奏

不适合的:
– 只有一个前端客户端
– 所有客户端需求基本一致
– 项目还在 MVP 阶段,快速验证比架构完美更重要


总结

BFF 不是一个花哨的架构模式。它的诞生是因为一个现实问题:多端共存时代,通用后端 API 已经满足不了不同前端的差异化需求。

它的价值在于把接口定义权从后端交到了前端团队手里。做 BFF 本质上不是让前端写后端代码,而是让最了解用户体验的人来决定数据怎么组织、什么时候拼好、怎么返回来。

但这层不是免费的午餐。多一层就多一次网络跳转、多一个部署维护的服务、多一份复杂度。要不要引入,什么时候引入,取决于你的实际场景,而不是架构潮流。

参考链接:
Sam Newman — Backends For Frontends
Microsoft Azure — BFF Pattern

📖 推荐阅读

看看这些文章,你可能会感兴趣:

React Server Components 指南:原理、实战与框架对比

浅析:Next.js 15 为什么成为 Agentic AI 应用标准?

React Compiler 1.0 来了:以后useMemo 和 useCallback 可以删了?

React 19 与 Vue 3.6:两种不同的前端哲学

DigitalOcean Referral Badge

This site is powered by DigitalOcean — reliable cloud hosting for developers.

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注