前端动态 API 生成与封装:前端 API 调用的一种思路

前端动态 API 生成与封装:前端 API 调用的一种思路

引子

在前端开发中,排除部分使用graphql的场景,一般还是需要调用大量的后端接口。传统的做法是手动编写每个 API 调用函数,或者使用像 Swagger Codegen 这样的工具生成客户端代码。但这两种方式都有各自的问题:

手动编写的问题:

  • 工作量大,接口多了容易出错
  • 后端接口变更后,前端需要同步修改
  • 代码重复,每个接口都是相似的 fetch/axios 调用
  • 难以统一管理(错误处理、认证、日志等)

代码生成工具的问题:

  • 需要额外的构建步骤
  • 生成的代码通常很冗长
  • 更新接口需要重新生成和提交大量代码
  • 难以自定义生成逻辑

思考:能不能让前端在运行时动态生成 API 调用函数?

这篇文章分享一下我的思路


核心思路

传统方式

javascript 复制代码
// api/customer.js - 需要手动编写每个函数
export async function getCustomerList(params) {
  const response = await fetch('/api/customer/list', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${getToken()}`
    },
    body: JSON.stringify(params)
  });
  return response.json();
}

// ... 还有几百个类似的函数

主流方式

后端写 Swagger / OpenAPI 文档,或api配置表

前端使用运行脚本根据配置表生成 SDK

生成出类似这样的标准文件:

javascript 复制代码
import { request } from '@/utils/request';

export const Api = {
  getCustomerList(params) {
    return request.post('/api/customer/list', params);
  },
  getCustomerDetail(id) {
    return request.get(`/api/customer/detail/${id}`);
  },
  updateCustomer(id, data) {
    return request.post(`/api/customer/update/${id}`, data);
  }
}

动态生成方式

前提:

  • 后端使用了BFF层
  • 确定的前端url约定,可以通过url推断出对应后端BFF层的API集合
  • 后端提供接口返回 API 元数据(可以根据url返回当前url页面可以调用的API集合)
javascript 复制代码
// 
// 后端接口返回 API 元数据
const apiMetadata = {
  "apis": [
    {
      "method": "getCustomerList",
      "path": "/customer/list",
      "requestMethod": "POST",
      "params": { "status": "String", "name": "String" },
      "returnType": "json"
    },
    {
      "method": "getCustomerDetail",
      "path": "/customer/detail/{id}",
      "requestMethod": "GET",
      "params": { "id": "Long" },
      "returnType": "json"
    },
    {
      "method": "updateCustomer",
      "path": "/customer/update/{id}",
      "requestMethod": "POST",
      "params": { "id": "Long", "data": "Object" },
      "requestBodyParam": "data",
      "returnType": "json"
    }
  ]
};

// 前端根据元数据自动生成所有 API 函数
generateApis(apiMetadata);

// 页面逻辑直接使用,不需要先定义,配置,或手动编写
window.api.getCustomerList({ status: 'active' }, (response) => {
  console.log(response);
});

// 也支持 Promise
const response = await window.api.getCustomerDetail.getPromise(123);

好处:

  1. 前端不需要编写任何 API 调用代码
  2. 后端接口变更,前端自动同步
  3. 可以实现统一的错误处理、认证、日志等Aspect
  4. 后端返回的API元数据甚至可以带一些蜜罐接口,前端代码永远不会调用,但是看起来很好被恶意利用的,而且可以定期变更,前端代码无需修改

因为接口是根据动态返回的元数据自动生成的,为了让前端同学拿到最新的接口文档,可以前端写一个函数,可以通过console调用格式化数据接口文档,类似swagger。另外后端如何定义,识别接口元数据呢,我主要是通过OpenApi的注解识别(一般方法上都已经加过了),只需要单独定义一个注解来标识哪些可以返回给前端。


生成Api部分逻辑实现设计

javascript 复制代码
[业务代码]
       ↓
[uniends.api - 中间件层]
       ↓
  ┌─────────────────────┐
  │  数据分析追踪        │ → 发送行为数据
  │  性能指标采集        │ → 上报到 APM
  │  错误日志            │ → 发送到 Sentry
  │  缓存检查            │ → 查询 Redis 或内存
  │  请求参数加工        │ → 自动补齐 headers
  │  A/B 测试           │ → 路由到不同后端 API
  │  自动生成traceid    │ →  生成唯一请求 ID
  └─────────────────────┘
       ↓
[实际后端 API 调用]
       ↓
[响应处理器]
       ↓
  ┌─────────────────────┐
  │ 成功/失败统计        │ → 上报性能指标
  │ 缓存写入            │
  │ 错误追踪            │
  │ 用户行为分析        │
  └─────────────────────┘
       ↓
[业务回调函数]

根据上方设计可以随时新增Aspect, 页面所有API调用都会经过这些中间件处理。

javascript 复制代码
日志记录       ─┐
埋点追踪       ─┤
缓存           ─┤
错误追踪       ─┤------→ → [后端]
性能监控       ─┤
重试/断路器    ─┤
鉴权          ─┘

实践中的经验

好处

1. 开发效率提升

之前: 每次后端新增接口,前端都要:

  1. 查看接口文档
  2. 手动编写调用函数
  3. 测试
  4. 提交代码

现在: 后端新增接口后,前端直接用,不需要任何额外工作。

2. 接口变更自动同步

后端修改接口url,参数或路径,前端:

  • 之前: 需要找到所有调用的地方,逐个修改或者需要更新接口定义配置表
  • 现在: 自动同步,不需要改任何代码,新增的参数不是必须的可以自动忽略,url变更对前端无感,因为前端是通过固定名称的函数调用。
3. 统一的最佳实践

所有 API 调用自动包含:

  • 认证 token
  • 错误处理
  • 请求日志
  • 性能监控
  • 重试逻辑
  • 超时控制

可以随时新增中间件处理逻辑

4. 更容易的重构

接口具体调用方式为统一封装的,更容易重构

  1. 你的项目中如何管理 API 调用?

    • 手写每个函数?
    • 使用代码生成工具?
    • 还是其他方案?
  2. 你会考虑使用动态生成吗?

    • 如果会,你的顾虑是什么?
    • 如果不会,原因是什么?

总结

以上思路已经有了基本实现,有需要可以交流

相关推荐
柯南二号2 小时前
【大前端】【Android】用 Python 脚本模拟点击 Android APP —— 全面技术指南
android·前端·python
2401_860319522 小时前
DevUI组件库实战:从入门到企业级应用的深度探索,如何实现支持表格扩展和表格编辑功能
前端·前端框架
LYFlied2 小时前
从循环依赖检查插件Circular Dependency Plugin源码详解Webpack生命周期以及插件开发
前端·webpack·node.js·编译原理·plugin插件开发
麒qiqi2 小时前
【Linux 系统编程】文件 IO 与 Makefile 核心实战:从系统调用到工程编译
java·前端·spring
IT_陈寒3 小时前
Vue3 性能优化实战:从10秒到1秒的5个关键技巧,让你的应用飞起来!
前端·人工智能·后端
gambool3 小时前
新版chrome Edge浏览器不再支持手动添加cookie
前端·chrome·edge
一只爱吃糖的小羊3 小时前
React 避坑指南:“闭包陷阱“
前端·javascript·react.js
weixin_446260853 小时前
八、微调后模型使用及效果验证-1
前端·人工智能·chrome·微调模型
by__csdn3 小时前
大前端:定义、演进与实践全景解析
前端·javascript·vue.js·react.js·typescript·ecmascript·动画