同样的功能,两套代码没区别?
外包和大厂的代码 · 差在凌晨三点
激励机制决定代码质量的下限;AI 把快乐路径写到几乎免费,差距全挤进了看不见的地方
一套 KPI 种出一套代码:五层防御,逐层拆开看
掘金上有篇文章,观点很硬:外包前端和大厂前端的代码差距,根源不是能力,是激励机制。外包按项目结算、按人天计费,验收通过、尾款到账,项目就结束了;大厂长期运营、持续迭代,一个隐藏的 Bug 可能在半年后被某个边缘场景触发,变成波及几百万用户的线上事故。我顺着这条线,把 V2EX 上十几年的甲方乙方吐槽翻了一遍。结论比他还狠一层:这套机制不仅解释了代码差距,还顺带解释了为什么到了 2026 年,外包这个模式正在被 AI 从下面拆台。
同一个功能,两套代码 假设决定上限
同一个需求交付到两边,看得见的部分趋同,看不见的部分分岔——这张图就是整篇文章的论点。
评估一个前端功能的代码质量,别数用了多少设计模式,数它覆盖了几种世界。外包代码只覆盖一种:理想世界。接口返回 200,数据结构完全正确,用户操作完全符合预期——在这个世界里,代码跑得很好,验收演示那天尤其好。大厂代码默认现实世界是个充满恶意的程序:接口可能返回 500,可能返回结构完全错误的 JSON,用户可能在网络断开的一瞬间点了提交,后端可能某次发版后悄悄改了字段名。
最后一行值得单独说。localStorage 对 XSS 攻击是完全不设防的——页面一旦被注入恶意脚本,攻击者能瞬间偷走所有用户的身份凭证。大厂用 HttpOnly Cookie、输入转义、CSP 内容安全策略把这些防线藏起来,正常使用时完全感知不到,遇袭时它们是最后一道墙。这些防线在验收清单上一样都没有,所以它们不出现在外包代码里,不是人的问题。
激励机制:一套 KPI 种出一套代码 定价问题
一条是跑到验收终点就结束的短跑,一条是没有终点线的长跑——代码长什么样,取决于你跑的是哪条道。
外包的商业模式决定了它的核心 KPI:用最短的时间、最少的人力,让功能在验收演示那一天跑通。可维护性、极端边界防御、长期性能劣化——这些东西不在验收清单里,自然也不会出现在代码里。这不是外包工程师偷懒,是商业模型决定的理性选择。
代码质量不是道德问题,是定价问题。 V2EX 上一条 2021 年的老帖里,有人把这件事说得比任何文章都透:「如果钱给的多,而且后续还可能要维护,就会考虑代码的质量,至少不能坑自己。如果钱又少,后续又不需要自己维护,那不是怎么快怎么来吗?」
同一个帖子里的甲方们则贡献了另一面的真实:有人花 4 万外包一个投稿系统,验收时没细看,钱付完了正式用起来到处是问题,十几页需求文档、答疑文档、思维导图全写了照样翻车;有人总结得刺眼——甲方如果真的花那么多精力去当外包的测试工程师,这份成本甚至大于自己开发。注意,这两拨人说的其实是同一件事:你为一个“交付即静止”的系统付的钱,买不到一个“会持续变化”的系统的代码。想要后者,要么加钱,要么加工期,要么自己写。
而大厂那一边,激励机制反过来了。系统上线后要被几十个人维护三五年,人员会流动,你今天写的每一行代码,半年后可能被一个完全不认识你的同事接手。所以大厂用严苛的 ESLint、强制的 TypeScript 严格模式、残酷的 Code Review,确保合入主分支的每一行代码,任何中级工程师五分钟能看懂。变量叫 data1、组件叫 NewPage2、一个文件塞 2000 行——写的人知道不用为后续负责,这些名字才敢出现。
五层差距,逐层拆开 拿着去审源码
一次请求要穿过五层关卡才能安全到达屏幕——少任何一层,平时看不出来,出事时全是窟窿。
把“看不见的代码”拆成五层,你就能拿着这张清单去审任何一份源码,包括你自己三年前写的。
第一层 · 全链路防御
外部输入 → 状态检查 → 运行时数据校验 → 安全渲染 → 错误兜底 → UI 降级 → 错误上报,一环都不能少。特别注意:TypeScript 只保证编译期类型,它不能证明 HTTP 返回值在运行时可信——接口数据和前端之间,永远隔着一层 Schema 校验。
第二层 · 系统维度
外包的典型页面是一个 500 行的文件:请求、loading、表格、分页、筛选全堆在一个组件里。系统维度的写法会把同一个页面自然拆开:数据 hook 管状态、service 层管接口封装和错误归一化、展示组件只渲染 props、边界状态完整覆盖 loading / empty / error。区别不在技术,在为一个“会持续变化”的系统做设计,还是为一张“交付即静止”的页面做实现。
第三层 · 异常路径
快乐路径谁都会写,差距几乎全在异常路径:接口挂了怎么办?返回为空怎么办?用户疯狂连点提交怎么办?组件卸载后异步请求才回来怎么办?最后这个有个经典形态——React 组件卸载后异步回调里还在 setState,控制台里的内存泄漏警告常年没人管。一个 cancelled 标记就能修的事,写不写,取决于你有没有被这类问题咬过。
第四层 · 可观测性
外包交付的系统几乎没有前端监控:页面崩了没人知道,接口报错只看到一个白页面然后默默关掉。大厂的系统背后是 Sentry 全局异常捕获、关键业务流程逐步打点、接口响应时间和错误率的实时大盘。代码不仅要能跑,还要能被观测——每个 catch 块里都带着完整的错误上下文,让值班同学第一时间定位。
第五层 · 安全意识
就是第一节表格最后那一行。Token 存储、输入转义、CSP,正常使用时感知不到,遇袭时是墙。
打开你手上的项目,先回答一个问题:这五层里,你的代码占了几层?
2026 年的新变量 差距被拉大
机器负责把代码写得越来越快,人负责在洪流里找出那个藏在快乐路径外的窟窿。
以上都是老结论。但 2026 年有件事改变了天平:AI 让快乐路径的代码几乎免费了,于是看得见的部分趋同,看不见的部分差距反而更大。V2EX 今年有个帖子很典型:某公司内部评审认为 6 万行代码足以实现所有功能,外包交付时交了 18 万行——大面积 AI 生成的产物。帖子里的高赞评论一针见血:「如果是大模型生成的代码,又何必找外包第三方呢?甲方自己调用大模型不就好了,而且甲方自己更懂自己的需求。」
另一条评论更值得抄在墙上:「改不动的代码便宜,改的动的代码贵。」把这两条放一起,外包这个模式的处境就清楚了:它最核心的卖点是“用更低的成本把功能堆出来”,而这个卖点正在被 AI 直接商品化。当甲方自己调模型就能生成能跑的系统,“外包比自建便宜”这个前提就开始松动。外包剩下的生存空间,只剩两样:一是 AI 也搞不定的复杂业务上下文,二是出事之后有人负责——而后者,恰恰是这套激励机制历来最不愿意为之付费的东西。
AI 时代值钱的不再是“把功能写出来”,而是“定义什么算对”。 写功能的部分在飞速贬值,能写验收标准、能设计异常路径、能搭监控告警的人,反而更贵了。因为机器产出的是代码,验收产出的是信任。所以别问“AI 会不会取代前端”。要问:你的工作里,有多少比例是在生产快乐路径,多少比例是在守护异常路径?后者才是你的护城河。
不管你在哪,五层是你自己的 六问
原作者最后有句话我很认同:外包的代码不是烂,它只是在一套不同的规则下做出了最理性的选择。如果你给大厂高级前端两周交付一个完整管理系统的预算,他写出来的代码大概率和外包没有本质区别——极度压缩的时间里,任何人都会砍掉现在看不到价值的东西。但有个动作是任何人都能立刻做的:在每个项目里多加一层错误兜底,多写一行类型校验。这些看不见的代码不涨薪、不进周报、验收时没人看,但它们是唯一能跟着你走的东西——换公司、换城市、换技术栈,都带得走。
把这张清单存下来,下次 review 代码时对着数:
-
每个网络请求,HTTP 状态码校验了吗?
-
接口数据过运行时校验了吗,还是直接信了 TypeScript 的类型?
-
loading / empty / error 三种边界状态 都有对应 UI 吗?
-
异步请求有取消机制吗,组件卸载后还会 setState 吗?
-
catch 块里是 console.error,还是带着上下文上报?
-
Token 在 localStorage 里吗?
六问里答不上来的,就是你这周可以补的第一课。
最后
外包和大厂的代码差距,拆到底是一道算术题:为看不见的东西付费的意愿,决定了代码的质量下限。大厂付得起,因为它运营得久;外包付不起,因为它交付完就走。而 2026 年的 AI 把这道题改了个条件——生成看得见的代码不再需要付任何人的费,于是所有剩余的价值,都压在了那些看不见的层里。
凌晨三点被 P0 电话叫醒过的人,和没被叫醒过的人,写的代码注定不是一个物种。但叫醒你的不一定是大厂的系统——也可以是你自己项目里那条没人看过的 catch。
看得见的代码越来越便宜,看不见的层越来越贵。