前端里的代码评审(Code Review)经常处于一个尴尬的位置:嘴上说重要,排期的时候永远靠后;拍脑袋定了个"看过就行"的流程,实际执行全凭个人心情。我所在的前端团队大概花了两个季度,把 Review 从"随缘互相瞅一眼"迭代成了现在这套基于 open-code-review 的标准化流程,PR 平均评审时长从 3.2 天压到 1.1 天,线上回归问题环比下降了四成左右。这篇文章把完整的方案、工具选型、流程设计、踩坑记录都整理出来,给正在被"怎么让 Review 真正落地"困扰的前端团队一份可以直接抄作业的参考。
适合谁看?前端组长、技术负责人、以及想推动团队质量建设但不知道怎么下手的同学。如果你只是一个人写代码,里面关于"审查维度"的部分同样有价值,可以拿来自查。下面所有内容都是我们实际跑过的方案和节奏,不涉及任何理想化设计。
1. 前端 Review 为什么容易做废:三个绕不开的团队现状
先泼一盆冷水。前端团队的 Review 做不起来,绝大多数时候不是成员不配合,而是流程设计本身就违背了前端开发的节奏。不把这个问题聊透,后面任何工具和规范都是空中楼阁。
1.1 快节奏迭代与"等评审"之间的天然冲突
前端是离业务最近的一层,需求变更频繁,联调依赖重,一个按钮的位置都可能因为产品一句话改三轮。在这种节奏下,开发同学的心理预期是"写完就合、合完就发"。一旦 Review 成为阻塞项,第一反应不是"我的代码有问题",而是"评审流程拖累了我"。
这不是态度问题,是流程设计没有考虑前端交付的时效性特征。我们早期试过"所有 PR 必须等两位同学确认后才可合并",结果就是代码堆积、合并冲突爆炸、线上事故频发。后来改成"小步提交 + 异步评审 + 关键路径保障",才把效率和质量同时稳住。
一个关键认知:Review 不是为了证明"我查过了",而是为了在代码进入主干之前,用最低成本完成知识校验和风险拦截。如果流程让开发者产生"Review 是负担"的体感,它一定不可持续。
1.2 前端 Review 的粒度难题:组件级还是业务级
后端接口评审可以聚焦在参数、事务、幂等上,边界相对清晰。前端不一样,一个按钮背后牵扯设计规范、组件库兼容、状态管理、埋点上报、权限控制、多端适配。你把粒度定在"函数逻辑"上,会漏掉设计层面的问题;你把粒度定在"整个需求"上,评审者大概率看不下去。
我们踩过的坑是:早期让评审人"整体看看",结果评审人打开 PR 看到 800 行 diff,直接放弃治疗,只回一句"看起来没问题"。
后来我们强制要求 PR 按模块拆分,并且给每个 PR 标注评审重点。前端 Review 的粒度应该以"可独立验证的交付单元"为准,而不是以"需求"为准。
1.3 "看过即通过"的假性共识最致命
很多团队不是没有 Review,是 Review 变成了形式主义的过场。打开 PR、滚到底、点通过,全程不超过两分钟。这种假性共识比不 Review 更危险,因为它制造了"我们有质量防线"的幻觉,让问题带着"已评审"的标签直接上生产。
打破假性共识,需要两个条件:一是评审内容有明确检查单,二是每条评审意见可追溯。这两个条件,单纯靠人的自觉做不到,必须依赖工具和流程去约束。这也是我们决定引入 open-code-review 这套开源方案的核心原因。
2. 六个前端特有的审查维度:不能拿后端评审清单直接套
网上能搜到的 Review 检查单大多是通用型的,"代码风格""异常处理""性能优化"这种空话占一半。前端要审查的东西比这些具体得多。下面这六个维度,是我们从近百次评审记录里总结出来的,每一个都对应过真实的线上故障。
2.1 组件设计的合理性:一眼看出三五年后的维护成本
组件审查不是看"能不能跑",而是看"这个组件放进团队代码库里,一年后还有人看得懂吗"。具体审查点包括:
- props 设计是否冗余。一个组件 props 超过 8 个且没有默认值分组,基本可以判定设计有问题。
- 组件职责是否单一。我见过一个"用户信息组件",内部偷偷调了订单接口,这种隐藏依赖是维护噩梦。
- 是否复用了团队组件库。自己造轮子不是不行,但需要说明理由。
- 样式是否通过 design token 而不是硬编码色值。
- 是否处理了异常态。loading、empty、error 三态是前端组件的基本素养。
一个实用技巧:评审组件时先看"这个组件被谁用、用了几个地方",再回头看实现。只在一个业务里出现一次的组件是私有组件,超过三个业务复用的组件才是公共组件,审查标准完全不一样。
2.2 状态管理:全局变量是前端维护性第一杀手
状态管理几乎是前端 Review 里最容易被忽略又最致命的部分。我们团队制定了几条硬性审查规则:
- 禁止在组件内部直接写未经封装的 localStorage / sessionStorage 读写。
- 全局 store 的 state 变更必须有 action / mutation 入口,禁止组件内直接修改。
- 新增全局状态前,先确认能否通过 props 传递或组件内 state 解决。
- 检查是否存在"状态冗余",即同一份数据存在多个数据源,且没有同步机制。
实际遇到最典型的案例:一个全局的 userInfo 对象,A 页面在 store 里改了它,B 页面通过 props 拿到了旧副本,两边展示不一致。排查了两天才发现是状态流向了不同地方。Review 时重点画"数据流经图",哪里数据源多了,哪里就会出问题。
2.3 性能:不是所有页面都配得上 useMemo
性能审查很容易走极端。一种是不管三七二十一,所有组件包一层 memo,结果依赖数组写错,子组件永远不更新。另一种是完全不看性能,列表页一次性渲染 2000 行。
我建议评审时关注"有没有明显的低垂果实":
- 大列表有没有虚拟滚动(react-window / vue-virtual-scroller)。
- 图片有没有懒加载和尺寸约束。
- 是否存在不必要的重复渲染,比如父组件 state 变化导致巨型子组件全部重绘。
- 接口返回的数据有没有做前端缓存,避免重复请求。
- 事件绑定是否在 useEffect 里正确清理。
这里多说一句:useMemo 和 useCallback 不是越多越好。React 官方都说了,过度优化比不优化更糟糕,因为依赖数组本身就是要维护的成本。评审时我会问作者一个问题:这个 memo 能带来多少收益?它会每次渲染都重新计算吗?答不上来,就把 memo 删了。
2.4 可访问性(A11y):看不见的"潜在用户"
前端团队最容易忽视的就是无障碍。国内业务里主动提 A11y 的需求很少,但不代表我们可以不做。从产品合规和用户覆盖两个角度看,这个短板早晚要补。
Review 里我会重点检查:
- img 是否有 alt,且 alt 不是装饰性冗余文案。
- 按钮和链接是否有可读的文本内容,而不是只有一个 icon。
- 是否存在纯鼠标操作的交互,键盘用户无法到达。
- 表单是否有 label 关联。
- 弹窗关闭后焦点是否回到触发元素。
这些点做起来不难,难的是每次都记得。我们的做法是把 A11y 检查放进 open-code-review 的自动检查插件里,同时人工评审时作为兜底。
2.5 兼容性与工程化:不是"它能在 Chrome 跑"就够了
前端 Review 里有一个新手高频问题:忘了考虑兼容性边界。Review 时要确认:
- 涉及的 API 有没有做兼容处理(比如
Array.prototype.at、structuredClone这些相对新的 API 在前端代码里直接用,需要确认 target 浏览器版本)。 - CSS 属性是否有前缀或回退方案。
- 移动端适配是否验证过安全区和横屏场景。
- 首屏性能是否考虑了弱网环境。
我见过一个比较惨的例子:团队用了一个新的 CSS 单位dvh,在低版本 WebView 上完全不生效,导致整个页面底部被刘海屏遮挡,线上用户反馈一大片。这类问题如果 Review 时多问一句"这个特性兼容性怎么样",就能避免。
2.6 安全审查:前端不是没有安全可言
很多团队觉得安全是后端的事,前端有什么好审的?实际上,前端的安全问题直接面向用户,影响面一点都不小。
最典型的是 XSS。React 默认对文本内容做了转义,但架不住有人用dangerouslySetInnerHTML、v-html或者拼接 HTML 字符串。Review 时必须确认所有 HTML 注入点都做了白名单过滤或转义。
另一个高频问题:敏感信息泄露。比如把 token 写在 localStorage 里没做过期处理、把加密密钥硬编码在代码里、把内部接口地址通过 console.log 打出来。这些我们在 Review 里都是零容忍,只要发现就直接打回。
3. 把 Review 流程跑起来:从提交规范到合并门槛的完整链路
维度聊完了,聊落地。这一段是整个方案的核心,我们把流程拆成了"提交前、评审中、合并后"三个阶段,每个阶段都有明确规则。
3.1 提交前的自我检查清单:让作者先过滤 80% 的低级问题
Review 效率低,很大原因是作者没做自检就把半成品丢上来了。我们在 open-code-review 的配置里内置了一份"提交前自检清单",作者在发起评审前必须逐项确认:
| 检查项 | 说明 |
|---|---|
| 本地全量测试通过 | 不只是新增用例,相关回归也要过 |
| 无冗余代码和注释 | 包括被注释掉的代码块、无意义的 console.log |
| devDependencies 是否有混淆 | 确保运行时依赖没有混入开发依赖 |
| 是否有未处理的 TODO/FIXME | 有则必须链接到对应 issue |
| 关键路径已自测 | 涉及支付、登录、数据提交等核心链路必须手动过一遍 |
| 是否有调试用的临时代码 | 比如写死的 mock 数据、硬编码的 userId |
这个清单不是摆设。我们会随机抽查已合并的 PR,如果发现连续两次提交都带着明显自检遗漏,会回到开发者个人去做专项沟通。实践下来,加入自检后 Review 轮次平均从 2.7 轮降到 1.4 轮,效率提升非常明显。
3.2 PR 的尺寸控制:小步提交是 Review 的氧气
我们团队有个硬性指标:单个 PR 的 diff 行数不超过 400 行(排除自动生成的 lock 文件等)。超过 400 行,要求拆分成多个逻辑独立的 PR。
为什么要定这个数字?学术研究和我们自己的体感一致:人一次能有效 review 的 diff 上限就在 400 行左右,超过之后注意力会断崖式下跌。与其让人硬着头皮看 800 行产生"放弃思考,只看格式"的副作用,不如强制拆分。
拆分的逻辑依据是:不按页面拆,按"可独立验证的交付单元"拆。比如"用户列表"这个需求,可以拆成"封装列表组件 + 接入接口 + 页面组装 + 空态处理"四个 PR,每个都能独立验证。
3.3 异步评审为主、同步会议兜底:适配前端交付节奏
前端团队分布在多个业务线上,强同步评审(大家约个时间一起过代码)很难推进。我们的方案是异步为主、会议兜底。
异步评审的机制是:作者提交 PR 后,通过 open-code-review 自动分配 2 名评审人,评审人可以在自己方便的时间段进行评审并留下评论。我们通过飞书机器人播报 PR 动态,超过 4 小时未评审会自动提醒。
同步会议只在两种情况下触发:一是评审人之间存在严重分歧、评论里来回拉扯超过 5 轮;二是涉及跨模块、跨团队的重大架构调整。同步会议控制在 30 分钟以内,只讨论分歧点,不在会上读代码。
3.4 评审 SLA 与升级机制:没有截止时间约束的评审都是耍流氓
"等别人评审"是前端交付阻塞感的主要来源。我们制定了明确的 SLA:普通 PR 必须在 4 个工作小时内完成首轮评审,紧急修复 PR(打了 hotfix 标签)必须在 1 小时内响应。
超时怎么办?有升级机制。第一层:飞书机器人自动私信提醒评审人。第二层:超时 1 小时仍未响应,自动升级到组长,由组长指定新的评审人或代为评审。第三层:紧急 PR 如果 30 分钟无人响应,允许作者合并后补评,但事后需要说明原因。
这个机制跑起来后,"评审不响应"这个最大的流程黑洞被堵上了。我们统计过,引入 SLA 之后首轮评审的中位响应时间从 7 小时降到了 1.5 小时。
3.5 合并门槛:别让"看起来能合并"成为最终标准
合并门槛不是越高越好,它要和团队节奏匹配。我们现在的配置是:
- 至少 1 个 approved,且没有"Request Changes"状态的评论。
- CI 全绿(lint、单测、构建、E2E 冒烟四项)。
- 无未解决对话(GitLab/GitHub 的 thread 必须 resolve)。
- 所属需求关联 issue 存在且状态正常。
早期我们要求 2 个 approved,后来发现对 5 人以下的小团队来说太慢,改成了 1+1 模式——1 个核心评审人必须通过,另一个可以是"前置通过"(评论了但没阻塞)。大需求(超过 400 行或影响核心链路)自动升级为需要 2 个 approved。
4. open-code-review 落地实录:从配置到使用的完整闭环
open-code-review 是一套开源的前端代码评审辅助方案,核心思路是把审查规则、流程规范、统计报告整合在一起。它不是"一个按钮解决所有问题"的银弹,而是把团队已经约定好的规则固化成了工具约束,减少"人治"带来的随意性。下面是我们实际落地的几个关键环节。
4.1 环境准备与安装配置
我们用的是 monorepo(pnpm workspace)结构,open-code-review 以 CLI 插件的形式集成进工程。安装很简单:
pnpm add -D open-code-review然后在项目根目录创建配置文件open-code-review.config.js:
module.exports = { // 准入规则:什么样的 PR 进入评审流程 rules: { maxDiffLines: 400, // 单 PR 最大 diff 行数 minReviewers: 2, // 最低评审人数 requireSelfCheck: true, // 必须完成自检清单 }, // 自动检查项:无需人工干预的硬性校验 autoChecks: { eslint: true, // 集成 ESLint 检查 stylelint: true, // 样式规范 secretScan: true, // 敏感信息扫描 dependencyCheck: true, // 依赖包安全审查 a11yCheck: true, // 基础无障碍自动检查 }, // 评审人分配策略 assign: { strategy: 'roundrobin', // 轮询分配,避免同一个人一直被指派 excludeAuthor: true, // 作者不能评审自己的 PR skillTags: true, // 根据 skill tag 匹配对应领域评审人 }, // 通知渠道 notify: { type: 'webhook', endpoint: process.env.REVIEW_WEBHOOK_URL, }, };这份配置的核心思路是:能通过工具自动检查的,就不要浪费人工。eslint 能抓到的格式问题、secretScan 能抓到的敏感信息,人工评审时根本不需要再看一遍。人工评审的精力要留给机器判断不了的东西:设计合理性、代码可读性、未来可维护性。
4.2 创建 Review 规则的两种方式:配置文件和注释指令
open-code-review 支持在仓库里维护一份REVIEW_RULES.md,所有评审人和开发者都能看到规则原文。我们团队把前面讲的六个审查维度整理成了可勾选的检查清单,评审人打开 Review 界面时默认加载这份清单。
另外还支持在代码注释里写指令,比如:
// review:skip // 跳过本文件的自动检测(需要注明原因) // review:focus // 标注这是评审重点区域 // review:owner:xxx // 指定必须由某同学确认我自己的经验是:review:focus特别好用。作者在提交前把最没把握的代码块标注出来,评审人优先看这些区域,能大幅减少"评审人花了大量时间看完结果什么都没说,而作者真正想让人看的地方被漏掉了"的情况。
4.3 与 CI/CD 集成:让门禁真正生效
配置写完,要在 CI 流水线里把 open-code-review 加进去。我们用的是 GitLab CI,核心 Stage 长这样:
review-check: stage: test script: - pnpm install - pnpm open-code-review --mode=ci rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'跑完的结果会回写到 MR 页面上。比如 diff 行数超标,CI 会直接失败,并在评论里提示作者"此 PR 超过 400 行,请拆分后重提"。敏感信息扫描发现疑似密钥,会提供具体文件和行号,同时通知到安全负责人。
这块要提醒一下:门禁设置不要太激进。我们第一次把所有自动检查项全部设为"失败即阻塞",结果光 ESLint 的历史存量问题就让团队一个上午无法合并任何代码。后来改进为两种模式:
- stderr 模式(仅警告):存量问题只展示,不阻塞合并。
- error 模式(阻塞):新增问题直接拦住,防止恶化。
判断标准很简单:存量看趋势,增量卡死。
4.4 生成团队 Review 报告:让改进有数据可依
open-code-review 有一个统计模块,会按周和按月输出团队 Review 报告。报告里我最关注三个维度:
- 平均首轮响应时间:衡量流程阻塞情况。
- 评审意见密度:每 100 行 diff 产生多少条有效评论,密度过低说明评审人可能只是走马观花。
- 评论类型分布:属于"确认型"(挺好/LGTM)还是"问题型"(这里会 xxx,应该 yyy)。问题型占比低于 30%,基本可以判定评审流于形式。
这个报告的价值在于:它不是 HR 考核工具,而是团队改进的方向盘。比如我们发现某个模块的评审时间总是特别长,点进去看全是关于状态管理的讨论,那下一步就是专门做一次状态管理的分享,把共性问题的讨论成本降下来。
5. 实操中的高频问题与排查技巧实录
流程跑起来之后,一定会遇到各种"规范之外"的意外。这里记录我们遇到过的高频问题和解法,希望你能少踩几个坑。
5.1 评审人回复"LGTM"但明显没细看,怎么办
"Looks Good To Me"(看起来没问题)是我们内部最警惕的回复。以前这种回复占了总评论量的近一半,直到我们在流程里加了"评审意见必须指向具体代码行"的约束——纯文本"通过"不生效,必须至少在代码行上留下一条评论,哪怕是"这里我没看懂,求讲解"都算。
有人觉得这是形式主义。但实际效果是:那些"没怎么看就想通过"的评审人会因为需要指行号而被迫真正去阅读代码。人对"明确指向某行"的行为比对"整体感知"更认真,这是行为设计上的一个小技巧。
5.2 资深同事的代码没人敢提意见
团队里如果有个技术最强的同学,他提的 PR 往往会收到一片"膜拜式通过"。这很危险,因为技术强不等于不需要评审,而且这种氛围会压制其他成员的表达欲。
我们的解法是:在 open-code-review 的分配逻辑里,对技术负责人的 PR 也会强制至少 2 名评审人,并把 skill tag 匹配到的初级/中级同学也加入评审名单。同时公开强调一条规则:"评审不是找茬,是团队共同对代码负责。任何人对任何人的代码都有质疑的权利,但质疑必须基于事实和技术理由。"
另外,我们自己内部约定了一个"反问推动"的方法:如果资深同学发现自己的代码被提了意见,第一反应不是解释"为什么这么写是对的",而是思考"为什么对方会有这个疑问",然后从沟通角度去回应。这个习惯养成后,团队的技术讨论氛围健康了很多。
5.3 作者不回复评论,或回复"好的"但从不修改
Review 里还有一种憋屈:你花半小时写了详细评审意见,作者回了个"好的",然后合并代码跑了,意见统统没改。后来加了两条规则堵住这个漏洞:
- 评论必须 resolve 才能合并:open-code-review 集成到代码托管平台的 thread 功能,所有评论必须由作者明确处理(修改/解释原因)后标记 resolve,否则合并按钮置灰。
- "不修改"必须有理由:不是所有评审意见都正确,作者可以不采纳,但必须回复不采纳的理由,比如"这里为了兼容旧数据,不能统一走新逻辑"。如果理由成立,评审人同意 resolve;如果达不成一致,走会议兜底。
> 注意:不要把所有评论都改成"强制必须改"的模式。好的评审文化应该是"提出异议的权利 + 解释理由的权利"双向成立。否则作者会为了通过而机械改代码,反而引入新问题。5.4 紧急修复需求绕开 Review 怎么办
业务线上一个紧急 bug,产品在旁边盯着,你说"先过一遍 Review 再合",对方可能直接炸毛。我们的处理方式是:紧急修复可以跳评审,但不能跳记录。
open-code-review 里有一个hotfix-bypass模式,允许作者跳过人工评审直接合并,但会自动做两件事:一是完整跑一遍自动检查(eslint、secretScan、依赖安全等,这些不能跳);二是生成一条"未评审待补"记录,进入团队周会追踪清单。事后 24 小时内,作者必须补充说明这次修复为什么紧急、为什么没走评审、后续如何避免同类情况。
用了这个机制后,"紧急绕过"不能作为常态漏洞存在了。一个季度下来,真正走 bypass 的 PR 只有两三个,都是确实需要马上止血的情况。
5.5 常见问题速查表
| 现象 | 可能原因 | 解决思路 |
|---|---|---|
| 评审响应极慢 | 没有 SLA 约束或 PR 过于庞大 | 设置响应 SLA + 机器人提醒 + 超时升级 |
| 评论意见全是风格问题 | 人工时间浪费在 ESLint 能搞定的事上 | 强化 open-code-review 自动检查,减小人工检查范围 |
| 评审密度低 | 评审人没理解自己该看什么 | 使用 REVIEW_RULES.md 明确审查维度 |
| 同一问题反复出现 | 评审意见没有沉淀成知识 | 定期从评论里提炼共性,更新团队知识库 |
| 作者批量回复"已改"但实际没改 | 评论无跟踪机制 | 强制 thread resolve 机制 |
| 评审人和作者吵起来 | 评审变成了人身攻击 | 立好规则:只对代码提意见,争议走会议兜底 |
| 新同事不知道评审流程 | 缺少新人指南 | 把 Review 规范并入新人入职 checklist |
6. 这套方案还能怎么延伸:Review 不止于代码合并
Review 的价值不应该在 PR 合并那一刻就终止。我们现在还在把 open-code-review 产生的数据往两个方向延伸。
6.1 从 Review 反哺团队知识库
每个季度,我们会让工程师翻出自己写过的评审意见,挑出"如果早点知道就好"的 5 条,整理成团队的技术周报分享。这些意见往往比任何教程都更有针对性,因为它们全部来自真实代码、真实场景。
比如有一次,有人在评审时发现一个"无界面的隐藏操作"——某个定时轮询接口在用户已经退出登录后仍在持续发送请求。这个问题的根因是全局定时器没有在登出时清除。这条意见被整理成"全局任务生命周期管理"的专题分享后,后面好几个月都没有再出现过同类问题。
6.2 与新人培养模型结合
评审记录其实是最好的"前端面试题"和"技能画像"。新同学进来了,让他看最近三周的评审记录,比让他背半天教程更高效——他直接看到了团队最真实的代码风格、踩坑教训、架构约定。反过来,团队带新人的同学可以通过新人的 Review 评论质量来判断他的技术成长曲线,比看代码提交记录更立体。
我们还有一个做法:open-code-review 的 skillTags 不只是给 PR 分配评审人,也会自动记录每个开发者在哪些领域(组件、性能、安全、状态管理)的评论最多。半年下来,每个人都有了清晰的技能侧重标签。这个东西在"全员通才还是培养专家"的讨论中,比拍脑袋有说服力得多。
6.3 最后分享一个个人习惯
我做完这些流程搭建后最大的体会是:工具解决的是"可执行性"问题,文化解决的才是"可持续性"问题。open-code-review 再怎么配置,也拦不住一个团队内心不认同 Review 价值的人。所以每次有新人入职,我都不会先讲流程怎么走,而是先讲一个真实的故事——某个线上事故是因为一行本可以在评审中被发现的代码造成的,我们为此排查了整整一个通宵。先让团队对 Review 有敬畏,再谈工具和流程,落地的阻力会小很多。
如果你们团队也在推进 Review 建设,建议先别急着把本文的方案全部照搬。挑一个最痛的环节(响应慢、密度低或没标准),先用工具解决这一个问题,跑出正向反馈后,再逐步叠加其他约束。这套 open-code-review 方案的灵活之处就在于:它不是一个锁死的框架,每条规则、每个开关都可以单独启停。渐进式改进,比一次性推翻重来要稳得多。