前端拆分与 BFF

共 35 题
📑 题目列表 35 题
#
★★★

1. 渐进式拆分(模块化/微前端)的依赖管理如何避免版本冲突与循环依赖?

渐进式拆分(模块化/微前端)中,依赖管理如何避免版本冲突与循环依赖?工程手段有哪些?

  • 依赖管理的冲突来源(共享依赖版本漂移、peer 依赖不一致)
  • 版本冲突治理(统一版本、peerDependencies、共享运行时)
  • 循环依赖的识别与消除(架构约束、lint、动态导入)

版本冲突来源:多包共享同一依赖(React、lodash)时版本漂移导致双实例(React 双实例直接破坏 hooks 与 context);治理手段——统一依赖版本(monorepo 的 resolutions/overrides 强制单版本、依赖图工具检测)、共享依赖外提(把 React 等列为 peerDependencies 并保证宿主提供单实例、微前端用 shared 配置共享运行时如 Module Federation 的 shared: { react: { singleton: true } })、构建期一致性校验(CI 检查关键依赖只存在一个版本)。循环依赖来源:模块间互相引用(A→B→A)、微前端间共享状态互相 import;危害:初始化顺序不确定、tree-shaking 失效、运行时 undefined。消除手段:架构约束(依赖方向单向、领域分层 lint 如 ESLint Boundaries)、重构消除(依赖反转、事件总线/依赖注入、提取公共依赖到共享包)、动态导入打破静态环(运行时按需 require/import,避免加载期互相引用)、循环检测工具(madge、dependency-cruiser 进 CI 阻断)。微前端场景还要注意跨应用直接 import 代码(应用间契约应走 API/共享包,而非源码互相引用)。

本题考察拆分架构的依赖治理。答题核心是"单实例共享运行时防版本冲突、依赖方向约束与提取公共依赖防循环",以及 CI 检测工具与微前端契约边界的工程化。

#
★★★

2. BFF 在 Token 代理、Refresh Token Rotation 与安全隔离的角色

BFF 在 Token 代理、Refresh Token Rotation 与安全隔离中扮演什么角色?前端如何受益?

  • BFF 代理模式(前端↔BFF↔下游服务)与 token 集中管理
  • Refresh Token 存放在 BFF(httpOnly cookie)的轮换机制
  • 安全隔离收益(前端不接触 refresh token、减少 token 暴露面)

BFF 模式:浏览器只与 BFF 通信,BFF 持有访问下游服务的凭证并代理请求(转发、改写、聚合),前端不再直连各微服务。Token 代理角色:前端登录后由 BFF 完成授权码交换与 token 获取,access token 由 BFF 管理(请求下游时附加),前端不接触原始 token 或只拿短期令牌。Refresh Rotation:refresh token 只存在 BFF 侧(httpOnly+Secure cookie 或服务端内存),BFF 在 access token 过期时用 refresh token 换取新对并轮换(旧 refresh 作废,防重放),前端无感续期(拦截 401→通知 BFF 刷新→重试原请求)。安全隔离收益:前端不存 refresh token(XSS 无法窃取)、access token 暴露面缩小(短期、BFF 内使用)、下游 API 不对浏览器开放(绕过前端直连被 BFF 白名单拦截);BFF 还可统一做 CSP、限流、审计与脱敏(响应裁剪敏感字段)。工程要点:BFF 的 cookie 域与 SameSite 配置(防 CSRF)、轮换并发处理(多个并发请求同时刷新只换一次)、BFF 无状态化(token 存 Redis 支持水平扩展)、BFF 与前端版本协同部署。

本题考察 BFF 的凭证安全架构。答题核心是"前端↔BFF 代理 + refresh token 存 BFF 轮换"的模式与安全收益(XSS 面缩小、下游隔离),以及 cookie 与并发刷新等工程要点。

#
★★★

3. 领域驱动设计(DDD)限界上下文在前端拆分的工程价值

领域驱动设计(DDD)的限界上下文(Bounded Context)对前端拆分有什么工程价值?如何应用?

  • 限界上下文的定义(领域模型边界、统一语言)
  • 前端按限界上下文拆分的收益(内聚、独立演进、团队自治)
  • 上下文间集成(API 契约、共享内核)与前端落地

限界上下文把复杂业务划分成边界清晰的领域(订单域、库存域、用户域),每个上下文有独立领域模型与统一语言(同一"订单"在不同上下文语义不同)。前端拆分价值:按限界上下文组织前端模块——订单模块只关心订单域(页面、状态、API、组件内聚),上下文间通过 API 契约交互而非共享内部模型,收益是模块内聚高、可独立演进(订单上下文重构不影响库存模块)、团队自治(每个团队拥有一个上下文的前后端)、业务语义对齐(产品/后端/前端用同一语言沟通)。前端落地:目录结构按上下文组织(src/order、src/inventory)、状态管理按上下文隔离(不共享全局 store 或只共享用户等基础上下文)、API 层按上下文划分 client、路由按上下文分区;上下文间集成用契约(OpenAPI/GraphQL schema)与防腐层(anti-corruption layer:把外部模型翻译成本上下文模型);共享内核(用户、权限)作为基础上下文统一管理。边界:避免过度拆分(小应用拆成七八个上下文反而成本高)、上下文间禁止跨领域直接改数据、字段命名冲突在契约层解决。

本题考察 DDD 思想在前端工程的应用。答题核心是限界上下文的边界与内聚价值、按上下文组织前端与契约化集成,以及防腐层与过度拆分的边界。

#
★★★

4. 微前端拆分粒度(按业务/按团队/按变更频率)的工程取舍

微前端拆分粒度按业务、团队、变更频率划分各有何考量?工程上如何取舍?

  • 三种拆分维度的定义与适用场景
  • 拆分粒度的成本(运行时、依赖、运维)与收益(独立发布、自治)
  • 粒度决策的工程方法(耦合度、团队规模、发布频率)

三种维度:按业务——每个业务域(电商的商品/订单/营销)独立应用,边界清晰、领域内聚,适合业务差异大、跨域协作少的系统;按团队——一个团队负责一个应用(含其页面与组件),配合康威定律(架构随组织),适合团队职责清晰的场景,但同页多团队需求会造成边界模糊;按变更频率——高频迭代模块(营销活动页)独立,低频核心模块聚合,适合"稳定核心+动态外围"的架构(类似 Stable Core 模式)。取舍考量:收益是独立发布(某团队发版不影响他人)、技术栈自治、故障隔离、规模解耦(千页级应用);成本是运行时开销(加载框架、通信)、依赖与样式隔离、重复基建(每个应用的监控/CI)、团队协作复杂度(跨应用联调、契约管理)。决策方法:按"耦合度 × 发布频率 × 团队边界"三维评估——耦合紧的不要拆、发布同步的不要拆、同一团队内部优先模块化而非应用级拆分;微前端是最后手段,先考虑 monorepo 模块化与组件级复用;拆分后每应用规模应足够小但不要碎(避免几十个应用互相通信的混乱)。

本题考察微前端粒度的决策模型。答题核心是三种维度的适用场景与"收益-成本"权衡,以及"耦合度×频率×团队"的评估方法与"先模块化后微前端"的降级建议。

#
★★★

5. 按业务域、页面、功能拆分的粒度权衡

前端按业务域、页面、功能三个层级拆分的粒度如何权衡?各自适用什么场景?

  • 三层粒度的定义(业务域>页面>功能)与依赖关系
  • 各粒度的拆分收益与成本(复用性、耦合、复杂度)
  • 粒度选择的原则(内聚、复用需求、变更频率)

三层粒度:业务域(order、user 等域级模块,含域内页面与组件,是最大的拆分单元);页面(单页作为单元,路由级懒加载,是默认的"可独立部署/加载"单元);功能(按钮、表单、卡片等组件级单元,是最小复用单元)。权衡维度:内聚性——业务域内聚业务规则,页面内聚交互流程,功能内聚 UI 行为;复用性——功能级最易复用(跨域共享按钮),页面级跨域复用少,业务域级不跨域复用;变更频率——高频变更放小单元(功能/页面独立更新),低频大模块聚合。工程权衡:以页面为默认拆分单元(路由懒加载天然支持),域内页面通过共享功能组件聚合(域内私有组件),跨域共享功能下沉公共组件库(公共层);业务域划分对齐限界上下文与团队;避免"功能级过度拆分"(每个按钮一个包,依赖与发布成本爆炸)与"业务域过大"(域内强耦合难维护);粒度选择原则:先按领域划域,域内按页面组织,跨域共享才提功能级公共库;评估指标:跨单元依赖数(越少越好)、共享复用率、独立发布需求。

本题考察前端拆分粒度的层次模型。答题核心是"域-页-功能"三层的定义与内聚/复用/变更三维权衡,以及"以页面为默认单元、跨域共享才下沉公共层"的选择原则。

#
★★★

6. 单体前端 → 模块化 → 组件化 → 微前端的演进路径

从单体前端到模块化、组件化再到微前端的演进路径如何设计?各阶段的推动力与退出条件是什么?

  • 各演进阶段的定义与推动力(规模、团队、变更频率)
  • 演进的前提条件与退出机制(何时该拆/何时该合)
  • 演进工程(增量改造、Strangler、风险控制)

演进路径:单体(一个代码库一个应用,适合小团队早期,成本最低)→ 模块化(代码层面按功能分目录/独立包,解决可维护性,推动力是代码膨胀)→ 组件化(组件库+设计系统+复用,解决重复开发,推动力是多项目重复)→ 微前端(应用级独立部署与团队自治,推动力是团队规模与独立发布需求)。每阶段有明确"退出条件":模块化阶段发现"改 A 模块必动 B 模块"说明边界错了;组件化阶段发现"跨项目共享需求超过复用收益"说明公共层过度抽象;微前端阶段发现"应用间通信与联调成本超过独立部署收益"就该合并(反向演进)。演进工程原则:增量而非重写——用 Strangler Fig 模式(新模块新架构、旧模块逐步替换)、先"模块化+组件化"打底(没有良好模块边界直接上微前端会放大混乱)、微前端前先验证"独立部署"的真实收益(发布频率是否真的不同);风险控制:演进期间双轨运行(新旧并行)、监控回归(性能与错误基线)、每阶段评估后再进下一阶段;团队规模是重要自变量(康威定律):小团队模块化够用,大组织才需要微前端。

本题考察架构演进的路径设计。答题核心是各阶段"推动力-形态-退出条件"的对应关系、增量改造(Strangler)与阶段评估,以及"先模块化后微前端"的顺序纪律。

#
★★★

7. Feature Flag 在渐进式拆分与 A/B 测试的工程价值

Feature Flag 在渐进式拆分与 A/B 测试中有什么工程价值?如何设计 flag 体系?

  • Flag 的类型(release/experiment/ops)与生命周期
  • 渐进式拆分的 flag 应用(新旧架构切换、灰度迁移)
  • A/B 测试的 flag 应用(分桶、指标关联、一致性)

工程价值:Flag 把"代码部署"与"功能上线"解耦——代码先合并部署,功能按 flag 控制开关,支持灰度放量、快速回滚、按用户/地域定向,是渐进式拆分与 A/B 的基础设施。渐进式拆分应用:新模块旧模块并存时用 flag 做"切换闸门"(新架构 flag 开 5%→50%→100% 逐步迁移流量,出问题秒关回旧架构)、按用户群定向迁移(内部用户先切)、拆分前后行为一致性对照(同一用户新旧版本数据对比);A/B 应用:实验 flag 按分桶分配(用户 id 哈希/随机),实验组与对照组体验差异,埋点上报实验标识做归因,flag 与指标联动(实验期结束自动收敛/全量)。设计要点:flag 类型分离(release flag 短生命周期、实验 flag 定期清理、ops flag 长期保留)、默认值安全(flag 服务不可用时的 fallback,通常关)、前后端一致(同一 flag 前后端共用同一来源,避免前端开了后端没开)、配置中心(管理后台+审计+灰度参数)、死代码清理(flag 全量稳定后移除分支,防止 flag 债)。A/B 特定:分桶哈希稳定(同用户同组)、样本量计算、显著性检验、实验与权限/灰度叠加时的优先级规则。

本题考察 flag 体系的工程化应用。答题核心是"发布解耦与灰度迁移"在渐进式拆分中的闸门作用、A/B 的分桶归因机制,以及类型分离、安全默认值与清理等治理要点。

#
★★★

8. 架构决策记录(ADR)与技术债务管理

架构决策记录(ADR)与技术债务管理在前端工程中如何实践?两者如何联动?

  • ADR 的结构(上下文、决策、后果)与记录时机
  • 技术债务的识别(复杂度、重复、遗留)与量化
  • 债务治理(偿还节奏、预算、与 ADR 的追溯联动)

ADR(Architecture Decision Record)是轻量决策文档:记录"决策背景(Context)→ 决策内容(Decision)→ 后果(Consequences,含代价与替代方案)",在前端工程中适用于状态库选型、路由方案、微前端拆分、构建工具升级等关键决策;价值是让"为什么这么做"可追溯(新成员快速理解、避免重复争论与重复踩坑),ADR 应随决策即时记录(不是事后补)、一人一议(简短)、按目录归档并在代码评审中引用。技术债务管理:识别——代码异味(重复代码、巨型组件、绕过架构的 hack)、遗留依赖(废弃 API、旧框架)、缺失的自动化(手工测试点);量化——用"债务清单"(条目+位置+影响+偿还成本估算)与客观指标(圈复杂度、重复率、Todo 数)而非模糊感受;治理——固定偿还节奏(如每迭代 20% 时间还债)、债务预算(新债必须登记并设到期日)、"大爆炸"式重构谨慎(高风险的还债用 Strangler 渐进)。联动:债务条目记录"当初的决策与 ADR 关联"(债源于某 ADR 的后果,偿还时更新 ADR 的后果部分)、新架构决策必须评估对既有债务的影响(避免新债)、ADR 评审会同时是债务评审会(决策即债务的源头)。

本题考察架构治理的工程化。答题核心是 ADR 的"背景-决策-后果"结构与即时记录、技术债务的清单化量化与节奏化偿还,以及"决策即债务源头"的联动机制。

#
★★★

9. 渐进式拆分(Strangler Fig Pattern)在遗留系统的工程价值

Strangler Fig Pattern 在遗留前端系统渐进式拆分中的工程价值是什么?实施步骤与风险是什么?

  • Strangler 模式的核心(新旧并存、增量替换、最终收敛)
  • 遗留前端拆分的实施路径(路由级替换、模块迁移)
  • 迁移风险(双轨一致性、数据/状态迁移、团队协调)

Strangler Fig Pattern(绞杀者模式):在保留旧系统的同时,用新架构"绞杀式"逐块替换旧实现,最终旧系统被完全替代——避免"大爆炸"重写的高风险(业务连续、增量反馈)。前端应用路径:以路由为替换单元——新路由指向新架构模块(新构建/新应用),旧路由继续走旧实现,入口按路径分流;模块迁移顺序按"影响可控、边界清晰"排序(工具函数→独立页面→核心流程),每个模块替换后独立验收发布。关键实施要素:统一入口(路由表/加载器按路径分发新旧)、共享状态与身份(新旧系统共用登录态与用户上下文,避免割裂)、契约先行(新模块与旧模块对接同一 API 契约)。风险与控制:双轨一致性——同一功能新旧实现行为差异(数据口径、交互细节)需对照清单验收;状态与数据迁移(本地存储、会话状态跨新旧切换的连续性);过渡期成本(两套代码与依赖并存、监控双写);团队协调(新旧职责分工、切换窗口沟通);退出条件——旧模块替换完成且稳定后删除旧代码(绞杀要"绞死",避免新旧长期并存失控)。监控上切换期间新旧错误/性能对比,保证替换不劣化体验。

本题考察遗留系统改造的成熟方法论。答题核心是"增量替换、路由级分流、契约先行"的实施路径与双轨一致性、状态迁移、及时清理的三大风险控制。

#
★★★

10. 架构演进与团队规模匹配(LSP、Conway's Law)

架构演进如何与团队规模匹配?LSP(稳定依赖原则/里氏替换)与康威定律(Conway's Law)如何指导前端架构?

  • 康威定律(系统结构随组织沟通结构)与团队-模块对齐
  • 稳定依赖原则(依赖方向指向稳定方向)与核心模块设计
  • 规模-架构匹配(小团队简单架构、大团队拆分自治)

康威定律:系统结构镜像组织沟通结构——两个团队频繁沟通的部分应在一个模块内(减少跨团队边界),反之按团队边界拆分模块(团队自治、接口契约);前端实践:团队边界→应用/模块边界(订单团队拥有订单模块)、跨团队共享下沉平台团队维护(组件库、基建),"逆康威"改造——为想要的架构先调整组织(组建平台团队再建共享平台)。这里借"LSP"所指的其实是稳定依赖原则(SDP,Stable Dependencies Principle):依赖方向应从易变模块指向稳定模块(业务页→组件库→基础库),稳定核心(内核、公共层)低变更高被依赖,易变外围(业务功能)高变更低被依赖——前端实践中公共组件库与设计 token 稳定化(严格 SemVer)、业务模块不反向依赖其他业务模块。规模匹配:小团队(<10 人)用单体+模块化(拆分的协调成本超过收益);中型团队按领域模块化+组件库;大型多团队(跨地域)才需要微前端/独立部署;匹配评估看"发布协调成本"——每次发版需要多少人一起等,即拆分信号;同时警惕规模不匹配:大团队硬塞单体(发布瓶颈)与小团队上微前端(基建成本爆炸)。

本题考察组织与架构的适配。答题核心是康威定律的团队-模块对齐、"稳定方向依赖"的核心设计,以及按团队规模与发布协调成本匹配架构形态。

#
★★★

11. Islands 架构与 RSC 的边界

Islands 架构与 React Server Components(RSC)的边界是什么?各自适用什么场景?

  • Islands 架构(静态 HTML + 可交互孤岛)的模型与实现
  • RSC 的模型(服务端组件/客户端组件边界、流式渲染)
  • 两者的边界与选型(静态优先 vs 动态应用、框架生态)

Islands 架构:页面默认为服务端渲染的静态 HTML(非交互),只有需要交互的区域(孤岛:轮播、表单、搜索框)单独打包 JS 并在客户端水合,孤岛间通过事件/状态独立通信,页面 JS 总量与交互点数量相关而非页面大小;代表是 Astro、Eleventy,适合内容型网站(博客、文档、营销页、电商商品页)。RSC:React 的组件模型扩展——服务端组件(只跑服务端、不打包 JS、可直接读数据库)与客户端组件(交互组件,标注 'use client')可自由嵌套,服务端组件可渲染客户端组件为其"插槽",配合流式渲染(Suspense 分块下发)与 Server Actions,代表 Next.js App Router;适合数据密集型与动态应用(B2B 后台、复杂业务系统),交互密度高。边界区分:Islands 强调"静态优先、按需水合"(孤岛是例外);RSC 强调"服务端执行与组件化数据流"(客户端边界是显式标注),RSC 的客户端组件仍是整体水合(除非配合 island 技术)。选型:内容站/营销页选 Islands(更轻、JS 更少);高交互复杂应用选 RSC(数据与组件无缝、生态成熟);两者非互斥——Astro 可嵌 React 组件,Next.js 也可配合部分静态化;共同点是"减少客户端 JS"的哲学,边界在"交互密度 × 数据复杂度 × 框架生态"。

本题考察新一代渲染架构的区分。答题核心是 Islands"静态+孤岛水合"与 RSC"服务端组件+客户端边界"两种模型的本质差异,以及按内容型/应用型场景与生态选型。

#
★★

12. Monorepo 与 Polyrepo 在大型前端项目的工程取舍

Monorepo 与 Polyrepo 在大型前端项目中如何取舍?各自优劣与适用场景是什么?

  • Monorepo 的收益(统一依赖、原子提交、跨包重构、CI 复用)
  • Polyrepo 的收益(独立发布、权限隔离、团队自治)
  • 取舍决策(规模、团队结构、工具链 pnpm/turborepo/nx)

Monorepo:所有包(应用、组件库、工具链)在同一仓库,收益——依赖统一(一次升级全部生效、避免版本漂移)、原子提交(跨包改动一次提交、CI 一次验证)、跨包重构容易(import 即所见)、共享配置与工具链(eslint/tsconfig 单点维护)、Code Review 全局可见;代价——仓库体积与 Git 性能(需 sparse checkout/浅克隆优化)、CI 构建编排复杂(需影响分析只构建变更包)、权限粒度粗(全仓库可读)。Polyrepo:每包独立仓库,收益——独立版本与发布(各自节奏)、权限与治理隔离(按仓库控制)、团队完全自治(自己的 CI/规范);代价——依赖漂移与版本地狱(升级跨仓库依赖难)、跨仓库改动流程重(多个 PR)、工具链重复配置、可见性差。取舍决策:需要原子跨包改动与统一依赖 → Monorepo(大多数中大型前端团队,配合 pnpm workspace + Turborepo/Nx 任务编排);多团队强隔离、独立发布节奏明显不同、组织边界硬(跨公司/外包)→ Polyrepo;混合模式——monorepo 内划分"发布组"(每个应用/库独立版本+发布通道)兼顾两者。工程要点:Monorepo 需要良好的包边界(否则退化为大泥球)、CI 影响图构建(只跑变更相关任务)、依赖策略(显式声明、禁止隐式引用工作区兄弟包)。

本题考察仓库策略的选型。答题核心是"统一依赖/原子提交"vs"独立发布/强隔离"的权衡矩阵,以及按团队结构与工具链做决策、混合模式与包边界治理。

#
★★

13. 垂直拆分(按业务域)相较水平拆分(按层)的工程边界

前端垂直拆分(按业务域)与水平拆分(按层:UI/状态/API)的工程边界是什么?如何选择与结合?

  • 垂直拆分(feature slice)与水平拆分(层切片)的形态
  • 垂直拆分的收益(内聚、变更局部化)与水平拆分的风险(跨层连带)
  • 结合模式(域内分层 + 域间隔离)与边界治理

水平拆分按技术层切分:components(UI)、store(状态)、api、utils 各自成目录,小项目直观,但随规模增长出现"改一个功能要跨多个层目录"(变更分散、关联断裂),且层间耦合(api 层改动影响所有页面)。垂直拆分按业务域切分:feature/order 内含该域的组件、状态、API 调用、hooks(feature-sliced design 的 slice 思想),变更局部化——改订单功能只动订单目录;收益是内聚(一个域的代码在一起)、可独立演进(域可单独拆包/懒加载)、职责清晰(跨域通过接口协作)。结合模式(推荐):垂直为纲(目录按域组织)、域内分层(域内再分 components/hooks/api 子目录)、跨域共享下沉(公共 UI/工具/基建层,只被域依赖、域间不互相依赖);边界治理:域间禁止互相 import(lint 约束)、共享层稳定化(变更走评审)、域依赖方向单向(业务域→共享层→基础设施);判断用"变更相关性"——经常一起改的代码放同一垂直单元,不一起改的分离;水平层保留"全局基建"(请求库、设计系统)而非业务逻辑。

本题考察目录架构的正交维度。答题核心是"垂直内聚/变更局部化 vs 水平分散/连带改动"的本质差异,以及"域为纲+域内分层+共享下沉"的结合模型与依赖单向约束。

#
★★

14. BFF(Backend for Frontend)层在前端的协作模式与工程实践

BFF 层的协作模式与前端工程实践是什么?BFF 由谁维护、如何与前端联调?

  • BFF 的职责(聚合、裁剪、协议转换、鉴权代理)
  • BFF 的归属(前端团队维护 vs 后端团队)与协作契约
  • 工程实践(类型共享、本地 mock、部署与监控)

BFF 职责:为前端定制后端——聚合多个下游服务(一个页面一次请求拿全量数据)、裁剪响应(只返回 UI 需要的字段)、协议转换(REST→GraphQL、字段命名对齐前端)、鉴权代理(token 托管)与缓存(页面级缓存)。协作模式:BFF 通常由前端团队维护(最懂前端数据需求,快速迭代页面级接口),后端团队维护领域服务;协作契约——BFF 与前端共享类型(OpenAPI/TS 类型生成,端到端类型安全)、BFF 与领域服务的契约由后端保证;前端页面开发依赖 BFF 接口先行(契约先行:先定义 schema 再并行开发)。工程实践:BFF 用 Node(NestJS/Fastify)或边缘函数(Cloudflare Workers/边缘网关);本地开发——BFF 本地起服务 + mock 下游(或契约测试),前端联调走本地 BFF;类型共享——monorepo 共享 types 包,BFF 响应类型驱动前端模型;部署与监控——BFF 独立部署(版本与前端解耦或同步发)、日志与 trace 贯通(前端→BFF→领域服务同一 traceId)、BFF 层性能监控(它可能成为瓶颈:聚合慢、超时聚合);错误处理——部分失败降级(一个下游挂了返回部分数据+标记),前端按 BFF 错误码展示。

本题考察 BFF 的落地协作。答题核心是 BFF"聚合/裁剪/代理"职责与前端团队维护的模式、契约先行与类型共享、以及本地 mock、独立部署与 trace 贯通的工程要点。

#
★★

15. Clean Architecture 在前端(Entity、Use Case、Interface)

Clean Architecture 的 Entity、Use Case、Interface 分层如何在前端应用?收益与边界是什么?

  • 分层职责(实体/用例/适配器/框架)与依赖方向(向内依赖)
  • 前端落地(领域层与框架解耦、用例编排数据流)
  • 收益(可测试、可移植)与边界(过度抽象、样板代码)

Clean Architecture 分层(由内到外):Entity(核心业务实体与规则,不依赖任何框架/UI);Use Case(应用业务规则:编排实体与调用端口,如"提交订单用例");Interface Adapter(把外部世界翻译成用例可用的形式:API 适配器、store、UI 组件);Framework(React/Vue/路由等)。依赖规则:外层依赖内层、内层不依赖外层(接口反转——用例定义端口,适配器实现端口),前端落地:domain/ 目录(实体+用例,纯 TS 无 React 依赖)、application/(端口接口)、infrastructure/(API、存储实现)、presentation/(组件层);数据流——UI 触发用例 → 用例调用端口 → 适配器执行 → 结果经用例返回 UI。收益:领域逻辑可独立测试(无框架 mock)、技术栈可替换(换 UI 框架不影响领域层)、复杂业务(规则多的系统)可维护性高。边界与代价:中小项目/表单 CRUD 型应用过度分层产生大量样板代码(interface/实现映射)反而拖慢开发;前端领域层常与状态管理(Redux 等)职责重叠(store 已承担用例编排),需明确分工(用例层做纯逻辑、store 做状态);建议"按复杂度局部应用"——业务规则复杂的核心域用 Clean 分层,简单页面直接组件+API;依赖注入在纯前端可用函数式(用例工厂注入端口)避免 DI 容器复杂度。

本题考察分层架构在前端的适配。答题核心是"实体-用例-适配器"的职责与依赖方向(内层纯净)、端口反转的落地方式,以及"按复杂度局部应用"避免过度抽象的边界。

#
★★

16. Hexagonal Architecture(端口与适配器)

Hexagonal Architecture(端口与适配器)在前端如何应用?与 Clean Architecture 的关系是什么?

  • 六边形架构的核心(端口-适配器、领域居中、外部隔离)
  • 前端落地(入站端口=用例、出站端口=API/存储接口)
  • 与 Clean Architecture 的等价关系与工程取舍

Hexagonal Architecture(六边形/端口-适配器):领域逻辑居于中心(六边形内核),通过"端口"(Port,接口)与外部世界交互——入站端口暴露领域能力(前端 UI 调用用例),出站端口声明领域对外部依赖的需求(数据持久化、API 调用、日志);"适配器"(Adapter)实现端口(REST 适配器、localStorage 适配器),外部技术(框架、数据库、第三方 SDK)都挂在端口之外,可替换而不影响内核。前端落地:内核——纯 TS 的领域模型与用例(无 React/DOM 依赖);入站端口——UI 层调用的用例接口(如 SubmitOrderUseCase.execute(input));出站端口——领域需要的接口(OrderGateway:fetchOrder、saveOrder),由基础设施实现(http 适配器、mock 适配器、IndexedDB 适配器);UI 组件通过适配器注入(props/context/组合)与内核交互。与 Clean Architecture 关系:本质等价——Clean 的 Entity/Use Case ≈ 六边形内核,Interface Adapter ≈ 端口实现与适配器,两者都坚持"依赖指向内侧、外部可替换";六边形更强调"端口对称性"(入口出口都是端口)。工程取舍:收益——测试友好(端口用 mock 适配器单测用例)、技术替换风险隔离(换请求库/存储不影响领域)、复杂业务可控;代价——间接层与样板代码、小项目收益低、前端框架(React)本身就是"适配器"导致分层感模糊;建议在领域规则密集的模块使用,UI 薄层应用直接调用 API 即可。

本题考察端口适配器架构。答题核心是"内核+端口+适配器"模型与双向端口的语义、前端落地的注入方式,以及与 Clean 的等价关系和按模块使用的边界。

#
★★

17. DDD(领域驱动设计)在前端的限界上下文(Bounded Context)

DDD 的限界上下文(Bounded Context)在前端如何识别与落地?上下文间的协作模式有哪些?

  • 限界上下文的识别(统一语言、业务边界)
  • 前端上下文落地(目录、状态、API 的组织)
  • 上下文协作模式(防腐层、共享内核、发布事件)

识别:限界上下文是业务能力的边界,识别信号——同一术语在不同场景语义不同("订单"在交易与售后语义不同则分属不同上下文)、业务规则内聚的领域(库存规则与支付规则独立)、组织边界(不同团队负责的领域);前端通过与产品/后端共同梳理统一语言(领域词汇表)划分上下文。前端落地:目录按上下文组织(src/bounded-contexts/order、src/bounded-contexts/inventory)、每个上下文的 store/API/组件内聚、上下文拥有自己的类型模型(不跨上下文共享领域对象,而是通过契约 DTO 转换);路由与导航按上下文分区。上下文协作模式:防腐层(Anti-Corruption Layer)——上下文间模型翻译,B 上下文消费 A 的数据时在自己的边界内转换为 B 的模型,防止 A 的模型污染 B(前端体现为:跨上下文 API 响应在消费方适配);共享内核(Shared Kernel)——双方共享少量稳定模型(用户、枚举),前端抽公共 types 包但保持最小;发布事件/契约——上下文间通过事件或 API 契约解耦(A 变化发布事件,B 订阅),前端对应跨上下文通信走全局事件/总线或公共 store 的有限字段。边界:前端上下文不要跨域改他人数据(状态越权)、共享内核保持极小并严格版本、上下文数量与团队/规模匹配。

本题考察 DDD 边界在前端的落地。答题核心是限界上下文的识别方法(统一语言)、前端目录/状态/类型的上下文化组织,以及防腐层与共享内核等协作模式。

#
★★

18. 前端代码分割(按业务域、按团队)的工程实践与现代应用

前端代码分割(按业务域、按团队)的工程实践有哪些?现代应用(路由级、组件级、条件加载)如何组合?

  • 分割维度(路由级/组件级/库级/按需条件)与收益(首屏、缓存)
  • 分割实现(动态 import、React.lazy/Suspense、预取)
  • 分割边界(过度分割、加载体验、SSR 配合)

分割维度:路由级——每个路由对应一个动态 import chunk(React.lazy + Suspense / Vue 的 component: () => import()),首屏只加载当前路由代码,是最主要的收益来源;组件级——弹窗/详情等低频组件独立 chunk(点击时加载);库级——大依赖(图表、编辑器)独立 chunk 并在使用时加载;条件加载——按特性(国际化语言包、权限模块、A/B 版本)运行时加载。实现要点:动态 import 的命名 chunk(webpack 的 magic comments:/* webpackChunkName: "order-page" */)利于缓存与排查;加载体验——配合 Suspense/loading 骨架、错误边界(chunk 加载失败重试与降级);预取策略——hover 路由链接时 prefetch(空闲预取高频页面)、首屏关键页预取;缓存策略——chunk 文件名 hash 化、公共依赖(vendor)独立分块(长期缓存)、按"业务域/团队"聚合 chunk 粒度(一个业务域一个 chunk 组,团队发布影响面可感知)。边界:过度分割——chunk 过多导致请求数爆炸与小 chunk 无收益(合并阈值,如 <20KB 不拆);分割与 SSR 配合(SSR 需要同步可用的模块,动态 import 需 await);性能预算——用打包分析与 CI 检查首屏 chunk 体积回归;按团队分割(微前端级)是独立应用而非单纯 chunk,注意共享运行时版本。

本题考察代码分割的完整实践。答题核心是四类分割维度与动态 import/Suspense/预取的实现、chunk 命名与缓存策略,以及过度分割、SSR 配合与体积预算的边界。

#
★★

19. ESLint Boundaries 插件在模块依赖边界的工程价值

ESLint Boundaries 插件如何约束模块依赖边界?其工程价值与配置实践是什么?

  • boundaries 插件的工作机制(tag 体系 + import 规则)
  • 边界规则定义(按层/按域/按应用的可见性)
  • 价值(架构约束可执行化、违规可视化、重构护栏)

eslint-plugin-boundaries 用"标签(tag)+ 规则(rules)"约束模块间依赖:给模块打 tag(如 @app、@domain/order、@shared/ui、@infra/api),规则声明"允许谁 import 谁"(如"业务域可依赖共享层,禁止共享层依赖业务域"、"域之间禁止互引"),ESLint 在 CI 与编辑器实时检查 import 路径,违反规则即报错阻断。配置实践:目录与 tag 映射(overrides 配置路径通配)、依赖规则按方向(allow/disallow)、可配置例外(公共基础设施互相依赖)与禁用说明(个别违规需注释理由);规则分错误/警告级别(先警告后收紧)。工程价值:把"架构约束"从口头约定/评审变成可执行检查——新人不会无意识破坏边界、重构(移动目录/调整分层)时护栏即时反馈、依赖方向可视化(配合依赖图工具)、跨团队协作时模块边界契约化(A 团队不能偷偷 import B 团队的内部实现);与现代模块化架构(feature-sliced、DDD 前端化、monorepo 包边界)配套,是"架构即代码"的低成本实现。实践注意:tag 设计要与架构文档一致(先定架构再写规则)、规则误报处理(豁免机制)、与 TS 的 no-restricted-imports 结合使用(boundaries 更语义化)、在 monorepo 中对包间依赖同样生效。

本题考察架构约束的自动化。答题核心是 tag+规则机制如何把依赖边界变成可执行 lint、配置实践(方向规则与豁免),以及"架构约束代码化"的工程价值与配套注意。

#
★★

20. Nx Tags 在 Monorepo 模块边界的工程实践

Nx Tags 如何在 Monorepo 中约束模块边界?工程实践与核心机制是什么?

  • Nx 的 tag 体系(project 打 tag)与 enforce-module-boundaries 规则
  • 边界规则的声明(allowed/forbidden 依赖方向)
  • 实践要点(tag 设计、CI 执行、与影响图结合)

Nx 用 tags 给每个 project(应用/库)打标签(如 type:app、type:feature、type:ui、type:util、scope:order、scope:shared),配合 ESLint 规则 @nx/enforce-module-boundaries 声明依赖约束:allowed 列表(某类项目可依赖哪些 tag 的项目)与 forbidden 规则(如"type:feature 只能依赖 type:ui/type:util/type:data,不能依赖 type:feature"或"scope:order 不能依赖 scope:payment")。机制:lint 时解析每个 import 的目标项目及其 tags,按规则校验,违规报错;规则支持通配与 depConstraints 数组(按源 tag 匹配允许的目标 tags)。工程实践:tag 设计先于实现——按"类型(type:)"与"域(scope:)"两个维度打标(类型约束层依赖方向、域约束业务隔离);规则分层——公共基建(type:util/type:data)可被任意依赖、业务 feature 只能依赖共享层与自己的数据层;结合 Nx 影响图——CI 只构建受影响项目时,边界违规会中断受影响项目检查;配合 Nx 的 project graph 可视化(nx graph)查看依赖关系;实践中为"临时合理违规"提供 eslint-disable 说明或依赖白名单。价值与注意:让 monorepo 的"包边界"可执行(防止库之间互相依赖成泥球)、支持团队分工(scope 隔离)、但 tag 体系需要架构治理(新增项目必须打标,可配置规则强制)。

本题考察 Nx 的边界治理机制。答题核心是"双维 tag + enforce-module-boundaries 依赖约束"的机制、按类型与域设计规则的实践,以及与影响图和可视化的结合。

#
★★

21. Turbo Generators 在新模块脚手架的工程应用

Turbo Generators(Turborepo 的代码生成器)在新模块脚手架中有哪些工程应用?设计要点是什么?

  • Turbo Gen 的工作方式(配置文件 + 自定义模板 + 交互式参数)
  • 新模块脚手架的应用场景(新建应用/库/组件、规范注入)
  • 设计要点(模板可维护、规范化强制、与 CI/文档集成)

Turbo Gen(Turborepo 的 codegen 工具)通过 turbo/generators 配置:config.json(生成器入口与描述)+ 自定义 generator(TS 编写,定义参数、交互提示、文件处理逻辑)+ 模板文件(handlebars 模板),执行 turbo gen 交互式收集参数并生成文件。工程应用:新模块脚手架——新建应用/库/组件/页面时一键生成标准骨架(目录、入口文件、测试、配置文件、README),保证"新代码出生即合规"(统一 tsconfig 引用、lint 配置、导出规范、命名规范);批量改造——已有代码的规范化迁移(加注释头、改目录结构、插入公共依赖);自定义模板满足团队规范(路由注册、story 文件、测试用例模板、边界 tag 自动打标)。设计要点:模板与项目规范同源维护(改规范改模板)、参数校验与默认值(名称、作用域、是否生成测试)、生成后校验(生成的代码过 lint/type 检查)、避免模板僵化(保留人工修改空间、文档说明生成产物)、生成器可组合(基础库+业务组件两级生成)、与 CLI 文档集成(turbo gen --help 列出团队可用生成器)。工程价值:降低新模块的认知成本与重复劳动、规范执行率提升(骨架即规范)、跨团队一致(每个团队生成相同结构)。

本题考察脚手架自动化的工程实践。答题核心是 Turbo Gen 的"配置+生成器+模板"机制、新模块脚手架与规范注入的价值,以及模板维护、参数校验与 lint 校验的设计要点。

#
★★

22. 前端公共库(common、ui、utils)的依赖边界与版本管理

前端公共库(common、ui、utils)的依赖边界与版本管理如何设计?边界失守的表现与治理是什么?

  • 公共库的边界定义(common 无框架依赖、ui 依赖设计系统、utils 纯函数)
  • 依赖方向与引用规则(业务→公共库,公共库间单向)
  • 版本管理(SemVer、peerDependencies、发布节奏)与边界失守治理

边界定义:utils(纯函数工具,零依赖或仅依赖基础库,可随处使用);common(共享常量、枚举、类型、请求封装,可依赖 utils,不依赖 UI 框架);ui(设计系统组件,依赖设计 tokens 与框架,不依赖业务逻辑);依赖方向——业务模块 → ui/common/utils,ui → tokens/框架,common → utils,禁止反向(ui 不依赖业务、common 不依赖 ui)与同层互引(common 内部不互相乱引)。版本管理:公共库独立发布(独立版本节奏,SemVer 严格——utils 改动影响面最大需保守、ui 组件破坏性变更要 major+codemod);peerDependencies 声明框架/设计系统版本范围(宿主提供,避免双实例);依赖策略——业务对公共库锁定主版本(^1.x 自动收 patch、major 升级走评审);公共库间依赖版本对齐(monorepo 内 workspace 协议或发布后依赖规范)。边界失守表现:ui 里写业务逻辑(出现订单相关组件)、utils 依赖 ui(循环)、业务直接复制公共库代码(分叉)、公共库互相依赖成环;治理——lint 边界规则(eslint boundaries/Nx tags 对包间生效)、公共库代码评审(业务语义入侵即打回)、定期依赖图审计(madge 可视化)、公共库体积与 API 变更监控(避免隐式 breaking)。工程上公共库"小而专"优于"大而全"(大杂烩库难边界化),发布频率与消费方数量成反比(被依赖越多变更越保守)。

本题考察公共库的治理体系。答题核心是 utils/common/ui 的边界与单向依赖规则、独立版本与 peerDependencies 管理,以及边界失守的表现与 lint/评审治理。

#
★★

23. BFF 接口聚合、协议转换、为不同端定制 API

BFF 的接口聚合、协议转换与为不同端(Web/App/小程序)定制 API 如何实现?设计要点是什么?

  • 聚合模式(并行/串行/编排)与超时降级
  • 协议转换(字段命名、数据形态、错误码统一)
  • 多端定制(不同端不同数据形态与鉴权策略)的 BFF 设计

接口聚合:BFF 把页面需要的多个下游调用编排为一个接口——并行聚合(Promise.all 并发拉取互不依赖的数据,注意超时上限与部分失败降级:某下游挂了返回部分数据+标志)、串行编排(有依赖链:先取用户再取其订单)、缓存(短 TTL 缓存热点数据降低下游压力);聚合接口要有超时预算(整体超时返回降级响应而非无限等)。协议转换:下游字段重命名与结构映射(camelCase↔snake_case、嵌套拍平)、类型转换(时间格式、枚举映射)、错误统一(把各下游错误码归一为前端友好的错误模型 code/message/retryable)、分页/排序参数适配。多端定制:Web、App、小程序数据需求不同(Web 富文本详情、App 精简字段、小程序低带宽),BFF 按端提供变体——路径/版本区分(/api/v1/web/detail vs /api/v1/app/detail)或同一接口按端参数(X-Client-Type)返回不同字段;鉴权策略按端(Web cookie 会话、App token、小程序 code2session);字段裁剪按端最小化(App 不需要的字段不下发)。设计要点:聚合接口按"页面场景"设计(一个页面场景一个接口,避免万能接口)、契约文档化(OpenAPI 供前端类型生成)、BFF 层监控(聚合耗时、部分失败率、下游依赖健康度)。

本题考察 BFF 的核心能力设计。答题核心是聚合的编排与降级、协议转换的统一模型、多端变体的定制策略,以及场景化接口与监控的设计要点。

#
★★

24. GraphQL BFF(Apollo Federation/GraphQL Mesh)

基于 GraphQL 的 BFF(Apollo Federation、GraphQL Mesh)如何设计?与 REST BFF 相比的取舍是什么?

  • Apollo Federation 的架构(子图、网关、实体引用)
  • GraphQL Mesh 的聚合模式(现有 REST/gRPC 源统一暴露)
  • 与 REST BFF 的取舍(类型安全、灵活性 vs 复杂度、缓存)

Apollo Federation:把多个后端服务作为"子图(subgraph)",各自暴露 GraphQL schema 并声明实体与键(@key 实体引用,如 Order 子图与 User 子图通过 userId 关联),网关(router)聚合子图 schema 为统一图,前端查询一次跨子图取数(实体解析跨子图按需 fetch)。GraphQL Mesh:把现有 REST/gRPC/OpenAPI 等异构源通过 handler 接入,自动生成 schema 与类型(可写 resolver 做映射与聚合),让旧 REST 体系获得 GraphQL 统一查询面——适合"已有大量 REST 服务、不想重写"的场景做渐进式 BFF。与 REST BFF 取舍:GraphQL BFF 优势——前端按需取字段(减少过取/欠取)、强类型(schema 即契约,生成 TS 类型)、一次查询聚合多资源、演进友好(加字段不破坏);代价——复杂度(schema 治理、缓存策略(GraphQL 查询难做 HTTP 缓存,需 CDN 持久化查询或 BFF 层缓存))、N+1 风险(解析器层需 DataLoader 批量)、调试工具链要求、安全(深度/复杂度限制防恶意查询)。选择建议:多团队多服务、字段个性化强、前端类型化要求高 → GraphQL(Federation 或 Mesh);简单聚合、少量接口、团队 GraphQL 经验少 → REST BFF(更快更直观);也可混合(GraphQL BFF 暴露聚合层,底层仍调 REST 服务)。

本题考察 GraphQL BFF 的架构形态。答题核心是 Federation 子图/网关模型与 Mesh 的异构聚合模式,以及与 REST BFF 在类型安全、缓存、复杂度上的取舍。

#
★★

25. tRPC(TypeScript-only)与 oRPC(跨语言)

tRPC(TypeScript-only)与 oRPC(跨语言)在端到端类型安全上如何工作?各自的边界是什么?

  • tRPC 的零代码生成类型推断机制(过程调用即类型)
  • oRPC 的跨语言契约(schema 驱动 + 多语言客户端生成)
  • 边界(纯 TS 全栈 vs 多语言团队、版本兼容)

tRPC:全栈 TypeScript 场景下,服务端用 tRPC 定义过程(query/mutation,输入输出由 TS 类型表达),客户端 import 服务端类型后直接类型安全调用(如 client.order.create(input)),类型由 TS 推断实时同步(改服务端类型,客户端编译即报错),无需代码生成与运行时 schema 校验(类型即契约,但运行时数据未验证——可配 zod 输入校验增强)。oRPC:面向跨语言(前端 TS、后端 Go/Rust/Python 等),用 schema 定义(Zod 兼容)描述 API 契约,生成各语言客户端/服务端类型与校验器,类型安全跨越语言边界(契约文件是单一事实源,变更走版本管理)。边界对比:tRPC——只适合前后端都 TS(或经 tRPC 的 openapi 插件导出给其他语言),收益是无缝类型体验、无 codegen 步骤;风险——类型漂移靠"同仓库同部署"(服务端与客户端类型不同步发布会导致线上错位)、运行时无默认校验。oRPC——适合多语言后端(跨语言类型安全)、契约可文档化/版本化;代价——需要 schema 维护与生成步骤、非 TS 侧的生态成熟度不一。选型:全 TS 全栈(Next.js/NestJS + React)优先 tRPC;后端异构、需要稳定跨语言契约优先 oRPC/OpenAPI 类方案;两者都可配 zod 做运行时校验兜底。

本题考察端到端类型安全的两种路线。答题核心是 tRPC"类型推断即契约、零 codegen"与 oRPC"schema 驱动跨语言生成"的机制差异,以及纯 TS 与多语言场景的选型边界。

#
★★

26. GraphQL BFF 与 tRPC/oRPC 端到端类型化

GraphQL BFF 与 tRPC/oRPC 在端到端类型化上的思路有何不同?如何组合使用?

  • GraphQL 的类型化路径(schema→代码生成→客户端类型)
  • tRPC/oRPC 的类型化路径(直接推断/schema 驱动)
  • 组合模式(GraphQL 做服务端聚合、tRPC 做前端直连)与取舍

类型化路径差异:GraphQL——schema 是单一事实源,通过 codegen(graphql-codegen)生成客户端类型与 hooks(TypedDocumentNode),类型安全但"生成-同步"有步骤(schema 变更需重新生成、CI 校验 schema 漂移);tRPC——无 schema,类型直接从服务端过程定义推断到客户端(同一 TS 类型体系,改一处全链路生效,无生成步骤);oRPC——schema 驱动(Zod 类型即契约),跨语言生成。组合使用模式:分层组合——后端多服务用 GraphQL Federation 聚合(或 Mesh 接入异构服务)作为"服务端图",前端通过 tRPC 调 BFF 层(BFF 用 tRPC 暴露类型安全的过程,内部转 GraphQL 查询),好处是"前端↔BFF 用最简类型通道(tRPC),BFF↔后端用标准 schema(GraphQL)",各自发挥优势;或整体 GraphQL(前端直接 codegen 消费网关)。取舍:全 TS 单栈→tRPC 直连最简;多服务聚合+多端(非 TS 端)→GraphQL 标准 schema 更通用(App/小程序也能消费);组合时注意类型链路不重复(BFF 层类型由 tRPC 表达,GraphQL 类型只存在于 BFF 内部,前端不直接生成 GraphQL 类型);端到端类型化的核心收益是"重构安全与契约即时反馈",选型看团队栈与端形态。

本题考察端到端类型化的架构组合。答题核心是 GraphQL codegen 与 tRPC 推断两条类型化路径的差异、前后端分层组合模式(tRPC 前端直连 + GraphQL 内部聚合),以及按团队栈与多端形态的取舍。

#
★★

27. API Gateway 与 BFF 的区别

API Gateway 与 BFF 的区别是什么?两者如何协同部署?

  • Gateway 的定位(统一入口、路由、鉴权、限流、协议转换)
  • BFF 的定位(面向端的聚合与裁剪)
  • 协同模式(Gateway 前置 + BFF 层)与职责切分

API Gateway(网关):面向"所有客户端与内部服务"的流量入口,职责偏基础设施——统一路由(按路径分发到服务)、全局鉴权(认证/授权拦截)、限流与熔断、协议转换(外部 HTTP↔内部 gRPC)、灰度/金丝雀路由、观测(全链路日志);它通常"不知道业务细节",是通用横向能力。BFF:面向"特定客户端"的业务适配层,职责偏业务——为该端聚合页面数据、裁剪字段、编排调用、端定制逻辑;它"懂这个端的业务需求"。区别总结:Gateway 横向(横切所有流量)、BFF 纵向(服务一种端);Gateway 通用化、BFF 业务化;Gateway 关注安全与流量治理、BFF 关注数据形态与体验。协同部署:浏览器 → API Gateway(统一入口:鉴权、限流、路由)→ BFF(按端聚合裁剪)→ 下游服务;Gateway 处理全局横切关注点(认证、限流、CORS、trace 注入),BFF 专注端适配(减少重复横切逻辑);也可以边缘网关(Cloudflare/云 API 网关)+ 边缘函数 BFF(部署在边缘就近执行);职责切分注意避免"Gateway 做了 BFF 的事"(网关堆业务逻辑会腐化)与"BFF 重复网关能力"(BFF 不自己做限流/鉴权,委托网关或复用中间件);部署形态:Gateway 独立集群(高可用),BFF 按端独立部署(Web BFF、App BFF 独立发布)。

本题考察服务端架构的层次分工。答题核心是"横向基础设施 vs 纵向业务适配"的定位差异,以及"网关前置+按端 BFF"的协同模式与职责切分纪律。

#
★★

28. GraphQL Federation 在多团队 BFF 协作的应用

GraphQL Federation 在多团队 BFF 协作中如何应用?子图治理与协作边界是什么?

  • Federation 多团队模式(每团队拥有子图、独立演进)
  • 实体与键的契约管理(跨子图引用、命名冲突)
  • 子图治理(schema 评审、路由升级、灰度与安全)

多团队模式:每个团队拥有并发布自己的子图(subgraph)——schema 定义、resolver 实现、独立 CI/CD;网关(router)负责合并子图 schema 并向客户端暴露统一 API;团队间通过"契约"协作:实体定义(@key 与外键字段,如订单子图声明 User 实体的 userId 引用)与命名空间(避免顶层类型重名,用命名前缀/统一命名评审)。协作流程:子图变更走 schema 评审(新增字段向后兼容、破坏性变更需团队间协调与迁移期)、子图发布前用 schema 校验(与网关预期兼容性检查,如 Rover 的 schema check 对比生产 schema)、网关升级(新子图版本生效经灰度);跨子图实体解析(Order 需要 User 字段时由网关按 @key 分发子查询),注意解析链路的 N+1 与延迟(DataLoader 与批量查询、@requires/@provides 声明)。治理边界:子图间禁止共享实现(不互相 import 对方 resolver)、公共类型(User、Money)放共享契约包或通过实体引用而非复制、命名冲突在 schema 评审解决、子图版本独立(团队发版不互相阻塞);安全——网关层查询复杂度限制与鉴权(子图服务端也应独立鉴权,不信任网关透传)、敏感字段按团队权限控制暴露(schema 不暴露内部字段)。监控:网关聚合查询的耗时、子图健康度(某子图慢影响全局查询,需超时与降级)。

本题考察 Federation 的组织级应用。答题核心是"每团队一子图、契约协作、独立发布"的模式,以及实体键管理、schema 评审与网关治理的安全/性能边界。

#

29. 前端路由层(router)与业务层的拆分在大型应用的工程实践

大型应用中前端路由层与业务层如何拆分?拆分后的协作模式与工程实践是什么?

  • 路由层与业务层的职责划分(导航/状态同步 vs 业务逻辑)
  • 拆分的实现(路由配置、守卫、数据加载与页面组件的解耦)
  • 协作模式(loader/守卫加载数据、页面消费)与边界

职责划分:路由层负责"导航结构与页面生命周期"——路由表(路径→页面组件)、守卫(登录/权限/导航拦截)、懒加载配置、路由状态(query/params)与面包屑/菜单的映射;业务层负责"页面内容与业务逻辑"——页面组件、业务 hooks、状态与 API 调用。拆分收益:路由配置集中可审计(权限声明、懒加载一目了然)、页面组件与导航解耦(可复用/可测)、导航过程中的数据准备有统一位置。实现:路由表声明式(meta 携带标题/权限/布局)、守卫集中(全局 beforeEach/loader 做登录与权限)、数据加载在进入前(React Router loader / Vue 守卫中 prefetch 或组件内加载——现代框架推荐 loader 层:路由负责"取数+校验",组件只消费 useLoaderData,组件不再自管加载逻辑);页面通过路由上下文(params/query)驱动业务 hooks,业务层不 import 路由 API(单向依赖:路由→业务)。协作边界:不要在业务层硬编码路由跳转(用命名路由/链接注入)、不要在路由层写业务规则(守卫只做通用检查,页面级规则放页面/业务层)、query 参数作为"可分享状态"需 schema 化(不塞业务对象)、错误承接(路由级 errorElement + 页面级错误边界分层)。实践:大型应用按路由域组织(路由配置文件分区)、代码分割与路由一一对应、路由变化驱动的状态重置(keep-alive/缓存策略)由路由层管理。

本题考察路由与业务的解耦。答题核心是"路由管导航结构与加载时机、业务管内容逻辑"的职责划分、loader/守卫统一加载的现代实践,以及单向依赖与错误承接的边界。

#

30. 状态管理的分层(UI、Domain、Infrastructure)

前端状态管理的分层(UI、Domain、Infrastructure)如何设计?各层的职责与边界是什么?

  • 三层状态的职责(UI 状态/领域状态/基础设施状态)
  • 分层状态库的选型(组件状态、全局 store、服务端缓存)
  • 状态流动与边界(跨层访问规则、同步/异步状态)

分层模型:UI 状态(组件本地状态:表单输入、弹窗开关、折叠、动画,用 useState/useReducer 即可,生命周期与组件一致);Domain 状态(业务实体与业务规则状态:当前用户、订单列表、权限集合,跨组件/跨页面共享,用全局 store(Redux/Zustand/Pinia)或服务器状态库(TanStack Query)管理,带业务语义);Infrastructure 状态(基础设施相关:请求状态(loading/error)、缓存与同步状态、连接状态(socket)、本地存储同步,常与服务端状态库/请求库管理,附缓存、失效、重试语义)。选型实践:优先"就近状态"(能放组件不放全局,减少全局复杂度);服务端数据用专用状态库(TanStack Query/SWR 管理缓存/失效/重试,不塞进手写 store);全局 store 只放"真正全局的业务状态"(用户、权限、主题);基础设施层状态(请求状态)由请求库封装(避免每个页面手写 loading/error 样板)。边界与流动:依赖方向——UI 状态可读领域状态(展示)、领域状态不依赖 UI 状态(业务层纯净)、基础设施状态由领域层消费(领域逻辑通过请求层取数);跨层访问规则——组件不直接操作基础设施缓存(通过领域层/请求层 API);同步/异步边界——UI 状态同步、领域状态可同步可异步(异步经请求层)、基础设施状态异步为主;分层治理信号——store 中出现"弹窗开关"(UI 状态上浮)或组件内出现"业务规则计算"(领域逻辑下沉)都是越界,需重构。

本题考察状态管理的分层架构。答题核心是"UI/领域/基础设施"三层的职责与选型(就近状态、服务端状态库、全局 store 只放真全局)、依赖方向与越界信号。

#

31. Web Components 在跨技术栈(React、Vue、Svelte)

Web Components 在跨技术栈(React、Vue、Svelte)场景下如何应用?边界与工程要点是什么?

  • Web Components 的标准形态(Custom Elements、Shadow DOM、Events)
  • 跨框架复用(一次编写多框架使用)与框架适配
  • 边界(表单交互、React 兼容、样式隔离、SSR)与要点

Web Components 用浏览器原生标准(Custom Elements + Shadow DOM + HTML Templates + Events)封装组件,不依赖框架运行时,因此可在 React/Vue/Svelte/Angular 等任何框架(甚至无框架)中直接使用——适合跨技术栈团队共享组件(设计系统组件、地图/播放器等重组件)或"框架无关"的长期资产。工程要点:跨框架使用时事件与属性约定——自定义事件(CustomEvent)通信(框架侧 addEventListener/dispatchEvent,React 需 ref 挂监听,React 对 web component 的事件 props 支持有限)、属性用 setAttribute(React 对 unknown attribute 的传递需小写化处理)、表单组件要处理 form-associated(与原生表单集成);样式隔离——Shadow DOM 封装样式(外部样式不影响内部),跨框架一致,但需注意主题/Design Token 的注入方式(CSS custom properties 可穿透 shadow 边界);框架集成差异——React 19 支持自定义元素属性/事件更好,Vue/Svelte 对 web components 支持成熟(Vue 的 customElements 配置、Svelte 直接可用);边界——SSR(shadow DOM 服务端渲染支持有限,需同构降级)、水合(框架对内部结构无感知,动画/插槽行为要自行实现)、无障碍(web components 的 a11y 需要显式实现 role/aria)、性能(每个组件实例的 shadow root 开销);工程要点:组件注册命名规范(带前缀防冲突)、版本与升级策略(多框架共享依赖同一包)、框架包装层(为各框架提供薄封装 adapter 以提升 DX)。

本题考察 Web Components 的跨框架工程化。答题核心是原生标准带来的框架无关性、事件/属性/表单的适配要点、Shadow DOM 样式与主题注入,以及 SSR 与无障碍等边界。

#

32. 前端架构从单体到微前端渐进式迁移策略的工程实践与边界

前端从单体到微前端的渐进式迁移策略如何设计?迁移的工程实践与边界是什么?

  • 迁移前的评估(收益验证、边界梳理、团队准备)
  • 渐进式迁移路径(路由分流、Strangler、共享基建)
  • 迁移的边界(何时停止、成本控制、回滚与监控)

迁移前评估:明确微前端的真实收益(独立发布频率、团队自治、故障隔离)是否值得成本(运行时、依赖、运维复杂度);梳理现有模块边界(耦合度高就不宜拆,先做模块化重构打底);团队准备(每个子应用的负责人与发布流程)。渐进式路径:第一阶段"治理打底"——统一构建、依赖与规范(monorepo 化、共享组件库、设计系统),把代码边界理清;第二阶段"路由分流试点"——选边界清晰、独立发布收益高的模块(营销活动页)切为独立子应用(基座+子应用共存),验证加载、通信、样式隔离、监控链路;第三阶段"规模化迁移"——按业务域/团队逐块迁移,共享基建(登录、权限、埋点 SDK、错误监控)沉淀为平台能力;全程 Strangler:旧模块保留,新模块渐进替换,稳定后清理。边界与成本控制:迁移不是无限拆分——定义"停止信号"(子应用数量达到维护上限、跨应用通信成本超过独立发布收益)与"合并信号"(子应用长期同步发布应合并回);每步迁移都有回滚方案(路由回切)与监控对比(性能/错误基线);避免"迁移即重写"(新瓶装旧酒:迁移时顺手重写业务导致风险放大);避免过度基建(先最小可用的加载/通信方案,再按需加沙箱、联邦模块);最终以业务价值评估迁移是否值得完成。

本题考察微前端迁移的完整方法论。答题核心是"评估-打底-试点-规模化"的阶段路径与 Strangler 增量替换,以及停止/合并信号、回滚与监控的成本控制边界。

#

33. BFF 的部署、扩展性与故障隔离

BFF 的部署、扩展性与故障隔离如何设计?工程要点是什么?

  • BFF 的部署形态(独立服务、边缘函数、同应用部署)与版本策略
  • 扩展性(无状态设计、水平扩展、下游连接池)
  • 故障隔离(超时/熔断/降级、下游依赖健康、BFF 自身监控)

部署形态:BFF 通常独立部署(与前端应用解耦,可独立扩缩容与发布)——传统 Node 服务(Docker/K8s)或边缘函数(Cloudflare Workers/Vercel/边缘网关就近执行);版本策略——BFF 与前端"同步演进但独立发布":接口契约版本化(/v1、/v2),前端灰度时 BFF 新版本同步灰度,避免前端已上线而 BFF 未就绪(发布顺序:先 BFF 后前端,或同一流水线原子发布)。扩展性:BFF 必须无状态(session 不落本地,token/会话存 Redis 或客户端)、支持水平扩展(多副本 + 负载均衡)、下游连接管理(连接池、keep-alive、HTTP/2 复用,避免每请求新建连接)、资源预算(CPU 密集聚合操作分流或异步化,防止阻塞事件循环);自动扩缩容(按 QPS/延迟指标)。故障隔离:下游调用统一超时(短超时+整体聚合预算)与熔断(下游连续失败快速失败,不拖垮 BFF)、降级(部分下游失败返回部分数据或缓存兜底)、依赖健康探测(health check 与下游状态上报);BFF 自身监控——聚合接口延迟分位、错误率、下游依赖各指标、BFF 进程指标(内存/事件循环延迟);故障场景演练(下游全挂时 BFF 仍能返回降级页面数据)。边界:BFF 不应持有状态(有状态会破坏水平扩展)、不应承担过重计算(重计算下沉领域服务)、故障隔离是"快速失败+优雅降级"而非"无限重试"。

本题考察 BFF 的运行工程。答题核心是独立部署与契约版本化发布顺序、无状态水平扩展与连接管理、超时熔断降级的故障隔离设计。

#

34. Service Worker + Cache API 在 BFF 前置缓存的工程价值

Service Worker + Cache API 在 BFF 前置缓存中有什么工程价值?缓存策略与失效机制如何设计?

  • SW 前置缓存的位置(浏览器侧缓存 BFF 响应)
  • 缓存策略(stale-while-revalidate、网络优先、缓存优先)
  • 失效与一致性(版本、TTL、按接口策略、离线支持)

工程价值:SW 位于浏览器与 BFF 之间,可缓存 BFF 响应,带来——弱网/离线可用(核心页面离线可读,BFF 不可达时降级为缓存内容)、减少 BFF 与网络压力(重复请求命中缓存)、首屏加速(二次访问秒开);与 HTTP 缓存(浏览器 HTTP cache)互补:SW 缓存可编程(按请求模式/策略精细控制)、可离线兜底、可后台更新。缓存策略:静态资源——cache-first(SWR:先返缓存+后台更新);页面/接口——网络优先(network-first,失败回退缓存,保证新鲜度优先)或 SWR(stale-while-revalidate:快速返回旧数据、后台刷新,适合列表/详情);关键实时接口(支付状态)——网络专用不缓存。失效与一致性:版本化——SW 缓存 key 带版本(cache name 含版本号),发布新版本时清旧缓存;TTL——按接口配置过期时间(缓存条目带 fetchTime,超时重新拉取);按接口策略表——SW 维护"路由模式表"(哪些路径缓存、什么策略、TTL),动态匹配;变更感知——BFF 响应带版本/ETag 类标记,SW 后台比对更新;离线支持——预缓存核心页面清单(install 时缓存),配合更新流程(新 SW 等待/跳过等待,页面刷新后接管)。工程边界:缓存一致性风险(用户看到旧数据——对账/支付等实时数据不缓存或短 TTL)、缓存爆炸(容量上限与清理 LRU)、调试复杂度(SW 缓存导致的"改了不生效"问题,需 bypass 工具)、与 BFF 鉴权(响应含用户私有数据时缓存需按用户分域或仅缓存公共数据)。

本题考察 SW 缓存层的工程化。答题核心是"离线可用+加速+减负"的价值、按资源/接口分策略的缓存模型,以及版本化、TTL、按用户分域与调试边界的治理。

#

35. tRPC(端到端类型安全 RPC)在 TypeScript Monorepo 的工程价值

tRPC 在 TypeScript Monorepo 中的工程价值是什么?如何落地与治理?

  • tRPC 的端到端类型安全在 monorepo 中的天然优势(同仓库共享类型)
  • 落地模式(apps 与 packages 的目录、server/client 划分、共享 types 包)
  • 治理(类型契约版本、运行时校验、跨包边界)

工程价值:monorepo 中前端(apps/web)与后端(apps/api)同仓,tRPC 的过程定义与类型天然共享——前端 import 后端导出的 AppRouter 类型,调用即类型安全(参数/返回值/错误类型全推断),"改后端签名 → 前端编译即报错"的即时反馈消除了接口文档漂移与 mock 层维护,配合 monorepo 的原子提交(前后端接口变更一次提交)实现真正端到端类型化。落地模式:目录划分——apps/web(客户端)、apps/api(服务端)、packages/trpc-contract(共享的 router 类型与 zod schema,或直接由 api 包导出类型);服务端用 initTRPC 建 router(query/mutation + middleware 做鉴权/日志),客户端 createTRPCClient 直连(浏览器端用 httpBatchLink 批量请求);跨包依赖——web 依赖 api 的 type-only 导出(isolatedModules 下用 import type),避免运行时打包后端代码("类型穿透":只导入类型不导入实现);monorepo 工具(tRPC 与 Turborepo/Nx 结合,构建影响图只重建变更侧)。治理要点:运行时校验——tRPC 默认类型即契约但无运行时校验,配合 zod 在 procedure input/output 做校验(防类型欺骗);版本与兼容——monorepo 单版本简单(同时升级),多版本场景(移动端单独仓库)用 tRPC 的 openapi 插件导出契约;边界——不把 tRPC 当成 ORM/业务逻辑层(procedure 内只做编排与校验,业务逻辑下沉领域服务)、middleware 统一鉴权(不要每个 procedure 重复)、错误处理(自定义 error formatter 统一错误模型给前端展示);CI——类型检查覆盖 web+api 全仓(一处类型破坏全局阻断)。

本题考察 tRPC 与 monorepo 的组合价值。答题核心是"同仓共享类型、原子提交、编译即反馈"的端到端类型化收益、type-only 跨包依赖与 zod 运行时校验的治理,以及 middleware 与错误模型的统一。