Javascript

Monorepo的真相:为什么大部分团队都用错了

Monorepo 最近几年成了前端工程化的显学。Google、Meta、微软都在用,Turborepo、Nx 这些工具层出不穷,到处都在讲 Monorepo 的好处。但我观察下来,大部分团队引入 Monorepo 之后,要么是用成了"巨型仓库",要么是过度拆分变成了"伪 Monorepo"。

真正的问题不是 Monorepo 本身,而是大家搞错了它的适用场景。

 

先说结论:Monorepo 不是银弹

 

很多团队看到 Google 用 Monorepo 管理几十亿行代码,就觉得自己也该用。但这里有个认知偏差:Google 的 Monorepo 是为了解决他们特有的问题——跨团队代码共享和依赖管理

你的团队有这个问题吗?

大部分团队的实际情况是:
- 前端就 3-5 个人,管理的项目不超过 10 个
- 业务相对独立,跨项目共享的代码不多
- 没有复杂的内部依赖关系
- 团队协作流程还没稳定下来

这种情况下,Monorepo 带来的复杂度远大于收益。

技术Leader的尴尬时刻

做技术管理这些年,我发现一个有趣的现象:越是成功的技术Leader,越不愿意分享自己踩过的坑。大家都在讲"如何打造高效团队"、"OKR落地实践"、"技术人才培养体系",却很少有人聊那些让人坐立不安的尴尬时刻。

但恰恰是那些尴尬时刻,构成了技术管理的真实底色。

 

当你意识到自己是瓶颈

 

2019年,我负责的前端团队刚从5人扩到10人。团队扩张后的第三个月,我突然发现一个问题:所有人都在等我review代码。

不是他们不主动,而是我在无意识中给自己设置了一个隐形职责——"技术质量守门人"。每个PR我都要亲自看一遍,每个技术方案我都要参与讨论,每个难题组员都会第一时间找我。

表面上看这是负责任,实际上是灾难。

团队的吞吐量被我一个人的工作时间卡死了。更糟糕的是,我发现自己在培养"等待型工程师"——遇到问题不是先思考,而是先找Leader确认。这不是我想要的团队文化。

那段时间很煎熬。一方面我知道必须放手,另一方面又担心代码质量下滑。最让人尴尬的是,当我试图"授权"时,发现自己根本不知道该怎么做。

过去几年里,我习惯了"事必躬亲就能保证质量"的工作方式。现在要求我"不插手也能保证质量",完全是另一套技能。

依赖管理的迷局:为什么升级依赖总是危险的

每次看到 Dependabot 或 Renovate 提的 PR,我的第一反应不是"好,及时更新",而是"又来了,这次会炸在哪"。

这不是危言耸听。见过太多次:一个看似无害的小版本更新,导致生产环境莫名其妙地挂掉;一个"修复安全漏洞"的补丁,带来了更严重的 breaking change;一个"只是升级 devDependencies"的操作,让 CI 流水线跑不起来。

行业里有个有意思的现象:所有人都在说"依赖要及时更新",但实际操作中,大家都在拖延。不是因为懒,是因为怕。

这种恐惧是有道理的。

 

语义化版本的美丽谎言

 

Semantic Versioning(语义化版本)告诉我们:`major.minor.patch`三段式版本号清晰明了,patch 是 bug 修复,minor 是功能新增,major 才是破坏性变更。所以升级 patch 和 minor 是安全的,对吧?

对个屁。

去年金融业务的一次故障,就是因为某个依赖的 minor 版本更新。库的作者认为他只是"优化了内部实现",所以只升了 minor。但这个优化改变了某些边界情况下的行为,恰好触发了我们业务代码里一个隐式依赖的逻辑。

TypeScript的代价:为什么严格模式在大型项目中变成了负担

TypeScript这几年几乎成了前端的"标配",不用TypeScript好像就落伍了。但我观察到一个现象:很多团队引入TypeScript后,开发效率反而降低了,尤其是启用了严格模式(`strict: true`)的项目。

这不是TypeScript本身的问题,而是大部分团队高估了自己的类型设计能力,低估了类型系统的复杂度。

 

类型系统的复杂度被严重低估

 

大部分人以为TypeScript就是"给变量加个类型",但真正在大型项目中用TypeScript,你会发现类型编程几乎成了一门独立的学科。

看一个真实的例子,金融业务中的表单配置系统:

BFF层的谎言:为什么大部分团队不需要它

最近在和几个技术管理者交流时,发现他们都在规划或已经落地了BFF(Backend for Frontend)架构。问为什么要做BFF,得到的答案惊人地一致:"解耦前后端"、"提升开发效率"、"这是最佳实践"。

但当我问:"你们团队有多少后端开发?前端开发呢?",答案通常是"后端6-8人,前端3-4人"。这让我意识到一个问题:大部分团队上BFF,可能不是因为真的需要,而是因为"别人都在用"。

我想聊聊这个话题,不是要否定BFF的价值,而是想说:很多团队高估了BFF的收益,低估了它的成本

 

BFF真正解决的问题

 

先说清楚,BFF不是伪需求。它在特定场景下确实有价值:

场景一:多端适配。你的后端API是为Web设计的,现在要支持移动端、小程序、IoT设备。不同端的数据需求、交互逻辑差异很大,用一套API很难搞定。这时候BFF可以为每个端定制API,后端保持稳定。

场景二:聚合调用。前端一个页面需要调用5-6个后端服务,串行调用太慢,并行调用又要处理复杂的依赖关系。BFF可以在服务端聚合这些调用,减少前端的复杂度和网络开销。

全栈工程师的最大误区:追求全能

最近看到一个问题:"全栈工程师是不是什么都要会?"下面的回答分成了两派,一派说全栈就是要前端后端数据库运维都精通,另一派说全栈是个伪概念,啥都会等于啥都不精。

两边都有道理,但我觉得都错了重点。

做了很多年全栈,从后端写到前端,再到带团队做架构,我的观察是:大部分人误解了全栈工程师的核心价值。全栈不是让你成为技术全才,而是给你一个完整的视角去理解系统、做决策、解决问题。

追求全能是个陷阱,追求全局观才是正道。

 

全能是个伪命题

 

先说个真实场景。

在金融业务中,经常会遇到性能问题。前端说页面慢是因为接口慢,后端说接口慢是因为前端请求太多,DBA说数据库压力大是因为查询写得烂,运维说服务器资源不够要扩容。

这时候如果你是个"全能型"全栈,你会怎么做?去优化前端的渲染逻辑、重写后端的查询语句、调整数据库索引、然后去研究服务器配置?

听起来很厉害,但实际上这是在用战术上的勤奋掩盖战略上的懒惰。

真正的问题可能是:这个需求本身就不合理,或者整个架构设计有问题。

代码复用的三个谎言:组件库、工具函数和Copy-Paste都不是答案

博客分类: 

最近看到前端组有同学在讨论要不要把某个逻辑抽成公共工具函数。这个场景太熟悉了,几乎每个团队都在纠结类似的问题:到底什么该复用,什么不该复用?

我的观察是,大部分关于代码复用的讨论都建立在错误的前提上。不管是组件库、工具函数库,还是Copy-Paste,都不是真正的答案。真正的问题在于,我们对"复用"这个概念的理解就是错的。

 

组件库的幻觉

 

前端圈最大的迷思之一是:我们需要一个强大的组件库。

这个想法听起来很美好。把所有常用的UI组件抽象出来,封装成统一的库,然后各业务线直接调用。听起来既能保证一致性,又能提高效率。

但现实总是很打脸。

我见过太多这样的场景:某个业务需要一个带搜索功能的下拉选择器,组件库里有个Select组件。产品经理说要加个"最近搜索"功能,组件库维护者说这是业务定制需求,不该放在公共组件里。业务开发者只好在外面包一层。然后产品经理又说搜索结果要支持分组显示,再包一层。最后这个Select组件被包了三层,代码比从头写一个还要复杂。

问题出在哪?出在我们把"复用"等同于"抽象"。

前端性能优化的迷思:为什么大部分优化都是在浪费时间

最近看到团队在讨论页面首屏加载优化,有人提出要把某个 10KB 的图片压缩到 8KB,说能省 20% 的体积。我突然意识到,前端性能优化可能是我见过的最容易被过度执行、也最容易做错方向的技术工作。

不是说性能优化不重要,而是大部分人根本不知道自己在优化什么,也不知道这个优化到底值不值得。

 

性能优化的第一个迷思:技术指标不等于用户体验

 

打开任何一篇性能优化的文章,你都能看到一堆指标:LCP、FCP、TTI、FID、CLS。这些指标确实有价值,但问题是,你真的理解这些指标背后的含义吗?

我见过一个团队花了两周时间把 FCP 从 1.2 秒优化到 0.8 秒,但实际上首屏还是白屏,因为真正有意义的内容要等接口返回才能显示。用户看到的"快",和监控平台上的数字,完全是两回事。

LCP 优化≠用户感知快。LCP 是"最大内容绘制",但如果你的最大内容是一张无关紧要的背景图,优化它有什么意义?用户真正关心的是"我能不能看到商品价格"、"我能不能点击购买按钮",而不是你的背景图加载了多快。

微前端的陷阱:为什么大部分团队不需要qiankun

微前端这几年很火,但我见过太多团队在盲目引入后陷入困境。最常见的情况是:团队只有3-5个前端开发,维护着2-3个业务模块,却花了两个月时间接入qiankun,结果代码复杂度翻倍,问题却没解决几个。

这不是qiankun的问题,而是大部分团队根本不需要微前端。

 

微前端解决的是组织问题,不是技术问题

 

很多人把微前端当成技术架构来看,这是第一个误区。

微前端的核心价值在于让不同团队能够独立开发、独立部署自己的模块,而不是解决技术上的模块化或性能问题。如果你的团队只有一个前端组,那么引入微前端就像一个人住别墅——空间是有了,但打扫卫生的时间也翻倍了。

我在金融业务中见过一个典型案例:公司有理财、基金、保险三条业务线,分属三个独立团队,各团队技术栈不同(React、Vue、Angular都有),发布节奏也不一致。这种情况下,微前端是合理的选择,因为组织边界清晰,技术隔离是刚需。

但大部分团队的情况是:前端是一个Team,后端可能分了几个服务,然后看到微服务很流行,就觉得前端也该"微"一下。这就是刻舟求剑了。

 

微前端带来的复杂度被严重低估

 

引入微前端后,你要面对的问题比想象中多得多:

状态管理的终局:不是Redux,也不是Context

前端圈对状态管理的执念,可能是过去十年最大的集体焦虑。从Flux到Redux,从MobX到Recoil,从Context API到Zustand,每隔一两年就会冒出一个"更简洁"的方案,然后大家又开始新一轮的重构和争论。

但我越来越怀疑一件事:我们在用前端的方式解决本不该存在的前端问题。

 

状态管理焦虑的根源

 

大部分前端开发者第一次接触Redux的时候,都会有类似的困惑:为什么一个简单的计数器需要写这么多代码?action、reducer、dispatch、connect,整整一套ceremony,就为了让组件拿到一个数字。

当时流行的解释是:"这是为了可维护性。" 等项目大了你就懂了。

确实,等项目大了,我懂了。但我懂的不是Redux的好处,而是我们把太多不该放在前端的状态放在了前端。

举个真实场景:用户的投资组合数据。

页面