普通视图

发现新文章,点击刷新页面。
今天 — 2026年2月5日首页

BFF 与 Next.js 的联系与组合

作者 codingWhat
2026年2月5日 01:13

最近在写一个Next.js的应用,其中API Routes被我当做轻量BFF,去做一些数据加工与处理,那么BFF 与 Next.js到底有什么样的联系呢?

一、概念先厘清

1. BFF(Backend for Frontend)

BFF 是为前端专门提供的一层后端,职责包括:

  • 接口聚合:把多个后端/微服务的调用合并成前端需要的少数接口。
  • 数据裁剪与适配:把后端 DTO 转成前端需要的结构,减少字段、改名、扁平化等。
  • 鉴权与会话:在 BFF 统一做登录态校验、权限校验,前端只关心「调一个接口」。
  • 协议与形态统一:前端只和 BFF 用 REST/JSON 等约定好的方式通信,不直接面对内部 RPC、消息队列等。

BFF 不负责 HTML 渲染,只负责「给前端提供数据接口」。

2. Next.js 与 SSR

Next.js 是一个 React 全栈框架,除了做前端 SPA,还提供:

  • 服务端渲染(SSR):在服务器上执行 React,生成 HTML 再返回给浏览器,首屏即完整内容,利于 SEO 和首屏性能。
  • API Routes:在 pages/api 下写接口,运行在 Node 里,对外提供 HTTP API,可当「小后端」用。

所以:

  • SSR 解决的是「谁在哪儿把页面渲染出来」的问题(服务器渲染 vs 浏览器渲染)。
  • BFF 解决的是「谁给前端提供接口、怎么聚合与适配」的问题。

二者一个偏「渲染与页面」,一个偏「接口与数据」,可以单独用,也可以一起用。


二、A项目中的 BFF 层:

在我们工作中,前端使用的接口由JAVA编写的BFF分层应用提供,在分层应用中去调用真正的内网接口。

2.1 架构概览

  • Web 层:Controller 暴露 HTTP 接口,路径多为 /xxx/api
  • Service 层:Facade 封装对下游业务服务的调用。

前端/移动端只认 BFF 的 URL,不直接调业务中台。

2.2 Controller:面向前端的接口与鉴权

以xxx申报记录查询为例(MobilexxxController):

@Controller
@RequestMapping("/xxx/xxxx/api")
public class MobilexxxController extends MobilexxxBaseController {

    @RequestMapping(value = "/query", method = RequestMethod.POST)
    @ResponseBody
    public MobilexxxDTO<Object> query(@RequestBody MobileuxxDTO<ZxxxRequestDTO> requestDTO) {
        // 1. 获取用户账户信息
        AccountDTO accountDTO = getAccount();
        // 2. 验证用户会话(BFF 统一鉴权)
        validateHelper.accountSessionCheck(accountDTO, ...);
        // 3. 从统一入参中取出业务数据,并注入用户信息
        ZxxxRequestDTO request = requestDTO.getData();
        request.setXm(accountDTO.getAccount().getName());
        // ...
        // 4. 调用 Facade,再统一封装返回格式
        Response<List<ZxxxResponseDTO>> response = mobilexxxFacade.query(request);
        return ResponseHandler.procResponseResult(response);
    }
}

可以看到 BFF 在这里做了:

  • 统一入参/出参MobilexxxDTO / MobileuxxDTO,前端只面对一种请求/响应形态。
  • 会话与鉴权getAccount()validateHelper.accountSessionCheck() 在 BFF 完成,前端无感知。
  • 数据注入:把当前用户姓名、证件号等写入请求再交给下游,前端不用传敏感信息。

2.3 Facade:聚合下游服务

Facade 不实现业务,只做「转发 + 聚合」:

@Service
public class MobilexxxFacade {
    @Autowired
    private RestfulClient restfulClient;
    @Autowired
    private RestfulUrlHelper restfulUrlHelper;

    public Response<List<ZxxResponseDTO>> query(ZxxRequestDTO request) {
        return restfulClient.postForJson(
            restfulUrlHelper.getxxxnwUrl("xxxx/query"),
            request, Response.class, List.class, ZxxResponseDTO.class);
    }
}

其他 Facade同理:BFF 通过 RestfulClient 调远端服务,对前端只暴露「一个接口、一种协议」。

小结:app 这一层是典型的 BFF——独立部署的 Java 服务,只提供 API,不负责页面渲染;职责是鉴权、聚合、适配,方便前端/移动端调用。


三、B项目中的 Next.js 与 SSR:

xxx-Next 是 Next.js 应用,同时用到了 SSRAPI Routes(充当轻量 BFF)

3.1 SSR:首屏服务端取数与渲染

使用 getServerSideProps 每次请求时在服务端拉取数据并渲染:

export default function GetData(props: PropsType) {
  const { err, data, msg = '' } = props
  // ...
  return (
    // ...
  )
}

export async function getServerSideProps(context: any) {
  const { id = '' } = context.params
  const data = await getDataById(id)  // 服务端请求接口
  return { props: data }
}

流程是:

  1. 用户请求 /data/xxx;
  2. Next 在服务器执行 getServerSideProps,调用 getDataById(id);
  3. 拿到数据后,在服务器上渲染 React,得到 HTML;
  4. 把 HTML 和序列化好的 props 一起返回给浏览器;

这样首屏就是「带数据的完整 HTML」,无需等客户端再发请求才出内容,这就是 SSR。这里 Next.js 的角色是「渲染层 + 在服务端发起数据请求」,数据来源也可以换成调用上面那套 Java BFF。

3.2 API Routes:"薄" BFF

点击提交按钮时,指向的是 Next 自己的接口:

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  // 数据加工
  const data = genData(req.body)  // 把表单 body 转成后端需要的结构
  const resData = await postData(data)
  // ...
}

这里 Next.js 的 API Route 做的是:

  • 接收: 传入的数据,如表单数据;
  • 转换genData(req.body) 把表单字段整理成接口需要的结构;
  • 转发postData(data) 再请求真正的后端。

也就是说,API Route 在这里扮演了一层薄 BFF:对前端暴露简单的一个 POST /api/data,内部做参数适配和转发,前端不直接调外部后端。

3.3 数据流小结

  • :浏览器 → Next 服务端 → getServerSidePropsgetDataById → 外部接口→ 服务端渲染 HTML → 返回。
  • :浏览器 POST 到 Next 的 /api/data → API Route 整理参数并 postData() → 再请求后端→ 根据结果处理。

SSR 解决「从哪拿数据、在哪渲染」;API Route 解决「提交时谁来做参数转换和转发」。两者都在 Next 里,但职责不同。


四、BFF 与 Next.js(SSR)的区别

维度 BFF(如 app 中的 Java 层) Next.js(SSR + API Routes)
主要职责 为前端提供聚合/适配后的 API 渲染 HTML 页面 + 可选的 API 端点
是否渲染 不渲染,只返回 JSON 等数据 服务端执行 React,输出 HTML
典型部署 独立服务(如 Java 进程、容器) Node 进程,同一应用里既有页面也有 API
技术栈 任意后端语言(本项目为 Java) Node + React(Next.js)
鉴权位置 常在 BFF 统一做 可在 API Route 或 getServerSideProps 里做
适用场景 多端复用同一套接口、多后端聚合 需要 SEO、首屏性能的前端应用

简言之:BFF 是「专门给前端的接口层」;Next.js SSR 是「在服务器上把页面渲染出来的方式」。一个偏数据与接口,一个偏页面与渲染。


五、BFF 与 Next.js 的联系与组合

  1. Next.js API Routes 本身可以当作轻量 BFF
    如 xxx-Next 的 /api/data:接收整理参数,再调后端。适合逻辑简单、不需要多语言/多后端聚合的场景。

  2. Next.js 的 SSR 可以消费 BFF
    getServerSidePropsgetStaticProps 里,用 getDataById 这类函数去请求「真正的 BFF」(例如 app 里的 xxx/xxx/api),而不是直接调业务中台。这样:

    • 鉴权、聚合在 BFF 完成;
    • Next 只负责「要什么数据、怎么渲染」,职责清晰。
  3. 组合方式示例

    • 把 xxx-Next 里 ajax.tsHOSTgetDataById 的 URL 指向 app 的 BFF 地址,数据就从 Java BFF 来。
    • 提交仍可先到 Next 的 /api/data,再由 API Route 调 BFF 的提交接口,这样前端只和 Next 打交道,BFF 由 Next 在服务端/API 里调用。

于是可以形成:浏览器 ↔ Next.js(SSR + API Routes)↔ BFF(app)↔ 业务服务。BFF 管「接口与数据」,Next 管「页面与一次转发/适配」。


六、总结

  • BFF:面向前端的接口层,做聚合、适配、鉴权,不负责渲染;本项目中 app 的 Controller + Facade 是典型实现。
  • Next.js SSR:在服务端按请求拉数据并渲染 React 成 HTML,首屏快、利于 SEO;xxx-NextgetServerSideProps 就是 SSR。
  • 区别:BFF 是「接口层」,Next.js(SSR)是「渲染方式」;BFF 可独立于前端技术栈部署,Next 是前端框架自带服务端能力。
  • 联系:Next 的 API Routes 可当薄 BFF 用;SSR 的数据来源可以、也适合来自 BFF;二者组合能同时获得「清晰的数据接口层」和「更好的首屏与 SEO」。

结合项目:app 负责「给前端/移动端提供统一、安全、好用的 API」;xxx-Next 负责「用 Next.js 把页面做出来(SSR),并用 API Route 做提交时的薄 BFF」。理解这一点,就能在架构上分清 BFF 与 Next.js(SSR)各自解决什么问题、如何配合使用。

❌
❌