返回文章列表

从技术分享到落地:业务组件库与通用函数库搭建

·6 分钟阅读·#前端#组件库#工程化#代码分层
目录 (7)

从技术分享到落地:业务组件库与通用函数库搭建

最近听了公司内部的一场技术分享,主题是如何提高代码稳定性。分享里重点讲了通过层级区分代码来降低耦合、提升可维护性:把前端代码按职责分为基础组件、业务组件、公用组件,以及通用业务代码、非核心业务代码等层次,并约定「外层可依赖内层、内层不依赖外层」,避免改一处牵动全局。听完后和组内小伙伴讨论了一轮,大家一致觉得现有项目里「公用组件散落各业务仓库」「通用函数没有单测」「新写一个组件不知道该放哪个目录」等问题已经影响到迭代效率,于是决定动手做两件事:搭建业务组件库搭建通用函数库,并在过程中把公用组件的测试用例和目录规范一并补齐。本文记录这次从分享到落地的过程和踩坑。


一、分享里的「代码分层」在讲什么

分享中的分层大致是这样划分的:

  • 基础组件:与业务无关的原子级 UI,如 Button、Input、Modal,一般由基础组件库或设计系统统一提供,很少改、可扩展。
  • 公用组件:多业务复用的组件和工具,如业务内统一的 Table 封装、日期选择、上传组件等,放在公共层,避免各业务各写一份。
  • 业务组件:只服务于某一业务模块的页面级或区块级组件,依赖公用组件和基础组件,不反向依赖其它业务。
  • 通用业务代码:跨业务复用的逻辑、工具函数、请求封装、常量等,与 UI 解耦,可被组件和页面共同引用。
  • 非核心业务代码:活动页、临时需求等生命周期短或变更频繁的代码,与核心业务隔离,便于后续下线或重构。

核心原则是依赖单向、职责清晰:基础层 → 公用层 → 业务层,避免业务组件被到处引用、通用代码里夹带业务判断。这样改一个业务模块时,影响面可控,回归范围也清晰。


二、我们面临的问题

讨论时大家列了几类具体问题:

  1. 公用组件、通用函数没有测试:散落在各仓库的 utilsshared/components 被多处引用,但几乎没有单测,重构或升级依赖时心里没底,只能靠人工回归。
  2. 新组件/新函数放哪里不清晰:没有成文的规范,新人或跨组协作时经常出现「类似组件重复造」「该抽成公用的没抽、不该抽的抽了」等情况,导致目录混乱、复用率低。
  3. 业务组件与公用组件边界模糊:有的组件只在两个业务用,有的未来可能下沉为公用,缺少「什么时候进组件库、放在哪一层」的决策依据。

因此我们决定:建独立的业务组件库与通用函数库,用仓库和目录把「公用」与「业务」隔开,并在库里补齐测试与文档,同时输出一份「新组件/新函数放哪里」的规范(含决策表或文档),让后续开发有据可依。


三、整体方案:业务组件库 + 通用函数库

  • 业务组件库:单独仓库(或 Monorepo 下的 packages/components),收纳当前多业务复用的组件及后续会复用的业务组件;按「基础 / 公用 / 业务」分子目录或分包,每个组件有文档和示例(如 Storybook),必须带单测才能合入。
  • 通用函数库:单独仓库(或 packages/utils),收纳与 UI 无关的工具函数、格式化、请求封装、常量等;每个对外暴露的函数都要有单测,并在 CI 中设覆盖率门禁(如不低于 80%, 这部分我么要求的是95%。)。
  • 目录与分层规范:写一份组内文档,说明「新写一个组件/函数时,先看是否已有类似实现 → 若没有,判断使用范围(单业务 / 多业务 / 全公司)→ 对应放到业务模块、业务组件库的某层、或通用函数库」,避免拍脑袋放目录。

这样,公用组件和通用函数的「无测试」问题通过入库门槛解决;「放哪个目录」通过规范 + 决策表解决;业务组件与公用组件的边界通过分层命名和文档明确下来。


四、业务组件库:目录与分层

我们采用「按层级分目录」的方式,便于按依赖关系理解和约束:

packages/components/
├── base/           # 基础组件(或直接依赖公司基础 UI 库)
├── shared/         # 公用组件:多业务复用
│   ├── DataTable/
│   ├── DateRangePicker/
│   └── ...
├── business/       # 业务组件:按业务域或产品线分子目录
│   ├── cert/       # 例如证书相关
│   ├── exam/       # 例如考试相关
│   └── ...
├── __docs__/       # 组件文档与「新组件放哪」的说明
└── package.json
  • base:若公司已有统一基础组件库,这里可以是封装或再导出;若没有,则放最底层的按钮、输入框等。
  • shared:明确会被两个及以上业务使用的组件,入库时需有文档 + 单测,禁止依赖 business/ 下的内容。
  • business:按业务域划分子目录,只允许依赖 base、shared 和通用函数库,不允许业务域之间互相引用。

「新组件放在哪」的决策:我们写了一份简短文档(并做成决策表放在文档站),大致逻辑是:

  • 只在当前业务模块用 → 留在业务项目内,不进入组件库。
  • 已有两个及以上业务要用、且与具体业务强绑定 → 进 business/某业务域/
  • 已有两个及以上业务要用、且与具体业务弱绑定(可配置、可复用)→ 进 shared/
  • 与业务无关的纯 UI 或基础能力 → 进 base/ 或交给基础组件库。

这样新人或协作方查文档就能判断,减少「放错目录」和重复建设。


五、通用函数库:范围与测试

通用函数库只收与 UI 无关的逻辑:日期/数字格式化、URL/参数处理、请求封装、权限判断、常量与类型定义等。与业务强绑定的(如「证书状态枚举」)放在业务侧或业务组件库的常量里,不塞进通用库。

测试要求:每个对外暴露的函数都要有单测。我们选用 Vitest(与现有 Vite 技术栈一致,启动快、ESM 友好),为每个工具模块配 *.test.ts,在 CI 中跑测试并做覆盖率门禁(例如整体不低于 80%,新增代码覆盖率不降)。这样重构或升级依赖时,跑一遍单测就能快速发现回归。

目录示例

packages/utils/
├── src/
│   ├── format/     # 日期、数字等格式化
│   ├── request/    # 请求封装、拦截器
│   ├── url/        # URL 解析与拼接
│   └── index.ts    # 统一导出
├── __tests__/
└── package.json

公用组件若依赖这些函数,通过 workspace:* 引用,保证版本一致且可追踪。


六、落地过程中的两个关键结果

1. 解决了公用组件、通用函数无测试的问题

  • 组件库:约定 合入 main 前必须通过单测,新增/修改组件需带测试用例(如用 Testing Library 测关键交互),CI 不通过无法合并。
  • 函数库:每个导出函数都有对应单测,覆盖率门禁在 PR 中检查,历史存量函数按「被引用次数优先」逐步补测,避免一次性负担过重。

2. 解决了「新组件/新函数放哪个目录不清晰」的问题

  • 在组件库仓库的 __docs__ 下写了组件分层说明新组件放置决策表(如上节),并同步到组内文档站;新人培训与 Code Review 时都会引用这份规范。
  • 通用函数库的 README 里写明收录范围(只收与 UI 无关的通用逻辑)和不收录的边界(业务枚举、业务接口封装等),减少「该不该放进 utils」的争议。

七、小结

我们解决了这两个问题:公用组件、通用函数长期没有测试用例——通过入库必须带单测和 CI 覆盖率门禁补齐;新组件、新函数创建时不知道放哪个目录——通过分层目录和决策表文档定好规范,大家按规范执行即可。