🧱 架构反思升级版:SSR / CSR 分层职责精炼总结
✅ SSR:不用 fetch,直接调用 BFF
-
SSR 业务请求不要用 fetch,直接调用 lib/service/server 中的 BFF 函数。
-
BFF 负责聚合逻辑,出现业务异常时
throw new BizError()。 -
SSR 层(如 server component、server action)
catch错误并处理。 -
后期如需缓存,接入 Redis(Upstash)统一包一层即可。
try {
const props = await fetchSectionProps(pageInstanceId, sectionName)
} catch (e) {
// SSR 自己处理错误逻辑
}
✅ API 层职责
-
API 作为暴露接口,仅做两件事:
-
调用 BFF 获取数据
-
catch错误并包装为统一 JSON 格式
-
try {
const data = await fetchSectionProps(id, name)
return jsonSuccess(data)
} catch (e) {
return jsonError(e.message, 1001)
}
✅ DAO 层保持纯净
-
只做数据库查询,不抛业务错误。
-
返回 null 或查询结果,由 BFF 层判断是否构成业务异常。
const record = await prisma.xxx.findUnique()
return record // null 就交给 BFF 判断
✅ CSR:用 react-query 管理状态
-
不再手写
fetch+useEffect -
统一封装为
useXXX()hook,用react-query管理请求、缓存、状态、错误
const { data, isLoading, isError } = useSectionProps(id, name)
✅ 架构分层职责明确
lib/
dao/ // 纯数据访问
service/
server/ // BFF 层,聚合 + 抛 BizError
client/ // CSR hooks,封装 fetch + react-query
app/api/xxx // API 路由,仅做包装
middleware.ts // 注入 tenant / user 上下文
❌ 过去的问题
-
❌ SSR 中滥用 fetch,哪怕在 server 内部也走 HTTP
-
❌ 没有利用 cookie + middleware 传递上下文
-
❌ 缺少 BFF 分层,api route 里直接写 dao + 判断逻辑
-
❌ CSR 没用 react-query,错失缓存、状态管理、数据依赖的优势
-
❌ 架构职责混乱,逻辑分散、耦合度高、可维护性差
✅ 当前结构收获
-
SSR 直接走函数调用,性能最优
-
API 封装一致错误格式
-
BFF 成为唯一业务判断中心
-
DAO 只做数据库访问
-
CSR 统一走 react-query + API
🧠 后续计划
-
所有 SSR fetch 替换为函数调用
-
BizError 类型体系补全(如 NotFoundError)
-
BFF 加 redis 缓存封装
-
react-query 配置 SWR 策略 + devtools
-
写清 SSR / CSR / API 职责对比文档

浙公网安备 33010602011771号