架构 - 后端从 flat routes/ 重构为 modules/<domain>/ 模块化结构(8个模块) - 四层架构:Route -> Service -> Repository -> Prisma - 新增 shared/ 基础设施(AppError 异常体系、ALS 上下文、prom-client 指标) - 前端 Toast/Skeleton/Alert 组件基建 + formulaService 模板 安全 - JWT 签名算法修复(HS256 用 createHmac 而非 createHash) - 密码哈希 async scrypt + timingSafeEqual - API Key 从 localStorage 迁移至服务端 runtime/config.json - Helmet 安全头 + rate-limit 全局限流 100 req/min - 全局 auth preHandler + RBAC + Ownership 中间件 颜色引擎 - 色匹配切换为 cube 粗筛 + CIEDE2000 精排 - PantoneColor 表 + 种子数据 + 搜索端点 - AI 配色 Prompt 注入成分库 colorant 列表 配方推演 - 本地优化引擎(同 category 替换 + 成本排序) - baseFormulaId 支持 + Pareto 散点图 文档 - ADR-0003 四层架构、ADR-0004 RBAC 授权模型 - 更新 ADR-0001/0002 - api-reference.md(29端点)、project-overview.md 部署 - Dockerfile * 2 + nginx.conf + docker-compose.prod.yml - 健康探针 + 优雅关闭 + pg_dump 备份脚本 - ESLint + Prettier + tsconfig strict
9.5 KiB
ADR-0001: 整体技术栈选型
状态: 已决议(2026-05-21 修订)
日期: 2026-05-20
修订: 2026-05-21
决策者: 架构评审
上下文
构建 AI 驱动的化妆品配方研发智能平台(纯 Web 端),涉及四大核心模块:颜色引擎(广色域渲染)、配方可视化编辑器(拖拽交互 + 实时 AI 反馈)、配方记录管理(结构化存储 + NL 搜索)、配方推演引擎(多方案并行优化)。需对前端框架、图表库、色彩科学库、后端架构、数据库等做出技术选型。
决策
1. 前端框架 → React 19 + TypeScript 5.7
| 候选 | 优势 | 劣势 | 结论 |
|---|---|---|---|
| React | 生态最丰富;ECharts/D3/color.js 均有 React 绑定;招聘成本最低;TS 成熟 | Hooks 学习曲线 | ✅ 推荐 |
| Vue 3 | 模板直观;Composition API 类型推导好 | ECharts 官方 React 绑定更成熟;D3 + Vue 组合不如 React 灵活 | ❌ |
| Svelte 5 | 编译时框架,运行时极小 | 生态较小;关键库适配风险;社区资源少 | ❌ |
| SolidJS | 性能优于 React;API 相似 | 社区太小(GitHub stars ~30k vs React ~230k);生产风险高 | ❌ |
决策:React 19 + TypeScript strict mode。
修订(2026-05-21):从 React 18 升级到 React 19。生态已稳定,React Compiler 带来额外性能收益。
2. 构建工具 → Vite 8
| 候选 | 优势 | 劣势 | 结论 |
|---|---|---|---|
| Vite | 原生 ESM 开发(毫秒级 HMR);Rollup 生产打包;零配置开箱;SSR 可选 | — | ✅ 推荐 |
| Next.js 15 | 全栈能力;SSR/SSG/ISR | 内部工具无需 SSR/SEO;增加复杂度;App Router 学习曲线陡峭 | ❌ |
| Remix | SSR 优先;Web 标准 | 同上;社区较 Next.js 小 | ❌ |
| CRA | — | 已停止维护;Webpack 构建慢 | ❌ |
决策:Vite 8,SPA 模式。平台为内部工具,无需 SEO/SSR。
修订(2026-05-21):从 Vite 6 升级到 Vite 8。
3. 状态管理 → Zustand
| 候选 | 优势 | 劣势 | 结论 |
|---|---|---|---|
| Zustand | 极简 API(无 Provider/Reducer);TS 完美;< 2KB;中间件(persist/immer/devtools) | — | ✅ 推荐 |
| Redux Toolkit | 完善的 DevTools;团队规范 | 模板代码多;概念多(slice/thunk/selector);过度工程化 | ❌ |
| Jotai | 原子化精细更新 | 原子拆分粒度决策成本高;对中型应用过度 | ❌ |
| MobX | 响应式直观 | 装饰器语法过时;与 React 18+ 严格模式兼容性问题 | ❌ |
决策:Zustand。服务端状态用 TanStack Query,客户端状态用 Zustand,边界清晰。
4. 路由 → React Router v7
| 候选 | 优势 | 劣势 | 结论 |
|---|---|---|---|
| React Router v7 | 最广泛使用;layout routes;v7 类型安全路由;社区资源极丰富 | — | ✅ 推荐 |
| TanStack Router | 编译时类型安全最强 | 生态较小;与第三方库集成案例少 | ❌ |
决策:React Router v7。
5. CSS 方案 → Tailwind CSS 4 + CSS Modules
| 候选 | 优势 | 劣势 | 结论 |
|---|---|---|---|
| Tailwind + CSS Modules | Tailwind 处理 80% 日常样式;CSS Modules 处理复杂定制(颜色盘);零运行时;Tailwind v4 CSS-first 配置 | 需同时掌握两套语法 | ✅ 推荐 |
| styled-components | CSS-in-JS,组件级隔离 | 运行时开销(~14KB);Server Components 不兼容趋势 | ❌ |
| Panda CSS | 编译时 CSS-in-JS | 较新(2024),生态不成熟 | ❌ |
| Vanilla Extract | 类型安全 CSS-in-JS | 构建步骤复杂;社区小 | ❌ |
决策:Tailwind CSS 4(原子化,处理布局/间距/响应式)+ CSS Modules(处理颜色盘 Canvas 容器、图表交互区等复杂定制场景)。
6. UI 行为组件 → Radix UI
| 候选 | 优势 | 劣势 | 结论 |
|---|---|---|---|
| Radix UI | Headless(完全控制样式);WAI-ARIA 内置;组件粒度合适;与 Tailwind 天配 | 无预置视觉风格(需要自行设计) | ✅ 推荐 |
| Ant Design | 开箱即用,组件丰富 | 企业后台感强;视觉定制困难;不适合创意工具;bundle 大 | ❌ |
| MUI | Material Design 完整实现 | 同上;Google 风格固化 | ❌ |
| shadcn/ui | 基于 Radix + Tailwind 预封装 | 封装度低,仍需二次开发 | — |
决策:Radix UI。平台 UI 需要与化妆品实验室品牌调性一致,Radix 的 Headless 模式允许完全定制视觉。
7. 图表 → ECharts
| 候选 | 优势 | 劣势 | 结论 |
|---|---|---|---|
| ECharts | 可视化类型最丰富(雷达图/桑基图/热力图等);React 绑定成熟(echarts-for-react);大数据集高性能 | 包体积较大(~1MB) | ✅ 推荐 |
| D3.js | 自由度最高;定制性极强 | 命令式 API;React 集成需大量封装;开发效率低 | ❌ |
| Recharts | React 声明式;组件化 | 图表类型有限;大数据集性能差 | ❌ |
决策:ECharts 作为主图表库,D3.js 作为辅助(颜色空间可视化等高度定制场景)。
8. 色彩科学 → colorjs.io
| 候选 | 优势 | 劣势 | 结论 |
|---|---|---|---|
| colorjs.io | 支持所有颜色空间(CIELAB/Display P3/LCH 等);ΔE 2000/CMC 计算;积极维护 | 社区较 chroma.js 小 | ✅ 推荐 |
| chroma.js | 轻量 API;流行度高 | 不支持 ΔE 2000;不支持 Display P3 | ❌ |
| d3-color | 与 D3 生态集成 | 颜色空间有限;无 ΔE | ❌ |
决策:colorjs.io。
9. 后端框架 → Fastify
| 候选 | 优势 | 劣势 | 结论 |
|---|---|---|---|
| Fastify | 性能最高(~60k req/s);插件生态完善(CORS/Swagger/Helmet);TypeScript 原生支持;schema 验证 | 社区较 Express 小 | ✅ 推荐 |
| Express | 最广泛使用;中间件生态极丰富 | 性能较差(~15k req/s);TS 支持需额外配置;回调风格 | ❌ |
| Hono | 极轻量(< 10KB);运行时无关(Node/Deno/Bun/Edge) | 生态较小;企业级插件不成熟 | ❌ |
| NestJS | 开箱即用架构(Module/Controller/Service);DI 容器 | 过度工程化;装饰器侵入性强;学习曲线陡峭;冷启动慢 | ❌ |
决策:Fastify 5 + TypeScript。插件体系完整且性能优异,适合 API 密集型场景。
10. 数据库 → PostgreSQL + pgvector
| 候选 | 优势 | 劣势 | 结论 |
|---|---|---|---|
| PostgreSQL + pgvector | 成熟稳定;pgvector 扩展支持向量搜索(HNSW 索引);ACID 事务 | 向量搜索性能不如专用向量 DB | ✅ 推荐 |
| MongoDB | 文档模型灵活;内置 Atlas Search | 缺乏 ACID;向量搜索需 Atlas | ❌ |
| Elasticsearch | 全文搜索最强 | 运维成本高;需额外同步数据 | ❌ |
决策:PostgreSQL + pgvector。配方数据是典型的关系型结构(配方→相→成分),PostgreSQL 的关系模型天然适配;向量搜索用于语义配方查找,pgvector 性能足够。
11. ORM → Prisma
| 候选 | 优势 | 劣势 | 结论 |
|---|---|---|---|
| Prisma | 类型安全;Schema-first;迁移工具成熟;Client 自动生成;关系模型直观 | 复杂查询性能不如原生 SQL | ✅ 推荐 |
| Drizzle ORM | 轻量零依赖;SQL-like API;性能接近原生 | 生态较新;迁移工具不如 Prisma 成熟 | ❌ |
| Knex.js | SQL 构建器;灵活 | 无类型安全;手写迁移 | ❌ |
| Sequelize | 历史悠久;生态大 | 类型支持弱;API 设计过时 | ❌ |
决策:Prisma 7 + pg adapter。项目中配方的关系嵌套深度大(Formula→Version→Phase→FormulaIngredient→Ingredient),Prisma 的关联查询和事务支持良好。
12. 包管理 → pnpm workspace
| 候选 | 优势 | 劣势 | 结论 |
|---|---|---|---|
| pnpm | 硬盘高效(硬链接);严格依赖;monorepo workspace 支持;速度快 | lockfile 格式与 npm 不兼容 | ✅ 推荐 |
| npm | 默认工具 | 依赖扁平化导致幽灵依赖;磁盘占用大;慢 | ❌ |
| Yarn | Plug'n'Play 模式 | PnP 兼容性问题多;社区分裂 | ❌ |
决策:pnpm。前后端独立 package,共享 workspace 协议。
13. 对象存储 → MinIO
决策:MinIO(S3 兼容),存储参考图片、导出文件。本地部署,S3 API 可无缝迁移到云。
修订(2026-05-21):MinIO 设为 docker compose
profiles: ["full"],默认不启动。当前无实际代码使用。
14. 部署 → Docker Compose + Traefik
决策:开发环境 docker compose up(PostgreSQL + MinIO(可选)),生产环境 docker compose -f docker-compose.prod.yml up(Traefik + PostgreSQL + Backend + Frontend)。
修订(2026-05-21):新增生产环境部署方案。Traefik 负责反向代理和自动负载均衡,Backend/Frontend 均已容器化。
15. 安全加固
| 组件 | 用途 | 添加日期 |
|---|---|---|
@fastify/helmet |
安全 HTTP 头(HSTS/X-Frame/X-Content-Type 等) | 2026-05-21 |
@fastify/rate-limit |
全局速率限制(100 req/min) | 2026-05-21 |
@fastify/swagger + @fastify/swagger-ui |
OpenAPI 文档生成 + /docs 交互式浏览 |
2026-05-21 |
后果
- 所有用户必须熟悉 React + Fastify + Prisma 三件套
- 数据库变更必须通过 Prisma Migrate,不可手动修改 Schema
- OpenAPI spec 作为服务契约,前后端类型同步
- 本地开发需 Docker 运行 PostgreSQL(pgvector 扩展)