
把尤雨溪三个字丢进任何一个前端群五分钟之内就能吵起来。有人把他当偶像说他是前端男神一个人撑起了一个生态也有人不服气觉得他不过是踩中了时代窗口换个人也能成。我在一线写了十来年前端做过小公司的全栈、也在大厂做过中后台和 C 端页面参与过框架选型、组件库治理、微前端拆分也当过面试官。我的结论可能有点反直觉尤雨溪最厉害的地方其实不是代码写得好——前端圈代码写得好的人多得是他真正稀缺的能力是持续十几年做取舍并且把取舍的结果讲清楚、卖出去。这篇文章我想做的不是复述一遍百科式的生平那玩意搜一下就有。我想拆的是他身上可被复现的那部分一个设计背景出身的人怎么一步步变成 Vue 和 Vite 的作者他在关键节点上做的那些技术决策背后是什么逻辑这些逻辑对一个正在准备前端面试、正在规划前端学习路线、或者正在焦虑AI 时代前端还有没有出路的普通开发者到底能抄走什么不管你是刚学完 HTML、CSS 就被 v-if 和 v-for 绕晕的新手还是已经能独立带项目、开始纠结要不要转 Agent 开发的老手下面这些内容都值得你看完。1. 一个设计系学生是怎么变成框架作者的聊尤雨溪的成长路径最有意思的不是他学了什么而是他缺了什么。他不是计算机科班出身大学读的是帕森斯设计学院这个起点决定了他后来看框架的视角和大多数纯工程背景的作者完全不同。这个差异在他后面做 Vue 的每一个决策里都能看到影子。1.1 帕森斯那几年他练的是上手手感不是算法竞赛设计训练给一个程序员的加成外人往往低估。设计学院教的核心东西是用户第一次接触某个东西的前三秒会发生什么他会不会困惑会不会放弃。你天天被逼着改一版又一版的作品集、被导师问你为什么这么排版慢慢就会对门槛这件事极度敏感。把这种敏感度搬到框架设计上就是另一套评判标准。多数框架作者关心的是这个抽象是否严密、是否可组合、是否学术上漂亮而尤雨溪更关心一个只会写 HTML 的人五分钟能不能跑起来一个能用的页面。这两个标准并不冲突但优先级不同优先级不同的结果就是 API 长相完全不同。我打个生活化的比方有的框架像一台手动挡性能车参数拉满、操控上限极高但你得先学会踩离合有的框架像一台调好的电瓶车拧一下就走了。哪种更好看你要去哪。但如果你是做企业后台、做中小型产品、做需要快速交付的业务电瓶车的价值被严重低估了。这个判断尤雨溪当年是押对了的。1.2 Google Creative Lab 那段把技术当表达工具的人公开履历里他待过 Google 的 Creative Lab也做过创意实验类的项目后来又在 Meteor 做过核心开发。这两段经历的性质差别很大但对他的塑造是同一件事技术不是目的表达才是目的。Creative Lab 那类项目的特点是技术选型完全服务于这个东西看起来酷不酷、体验顺不顺而不是架构是否可维护十年。在这种环境里待久了你会形成一种本能先想用户看到什么再想代码怎么写。这个顺序恰恰是很多纯工程背景开发者倒过来的——先想架构怎么优雅再去想用户要什么。后来 Vue 的很多细节都能看出这种痕迹。比如单文件组件SFC把 template、script、style 放进一个文件里从工程学的角度没什么必要甚至有人批评它把三种语言塞一起不干净但从一个人维护一个页面的视角看它就是最省心的组织方式。再比如 Vue 官方文档的质量在开源框架里常年属于第一梯队示例可以整段复制粘贴直接跑这背后还是设计思维——文档就是产品的一部分。提示这一点对普通开发者更有用的是反过来用。如果你现在写业务代码时先想的是我这个 Hook 抽得漂不漂亮而不是用户点完之后会发生什么那你可能已经跑偏了。抽象是手段交付才是目的。1.3 Vue 的起点一个抽出来的副业项目而不是一个要做框架的宏愿Vue 的诞生故事很朴素。他当时在用 Angular 做原型data-binding 那套东西用起来确实爽但 Angular 体量太重而且它的野心太大——路由、依赖注入、模块体系、测试方案全都要管。你只想给一个页面加一点数据驱动的交互却被塞进一整套世界观。于是他做了一个很多老手都会做但很少坚持下来的动作把我真正想要的那一小块抽出来。那一小块就是响应式数据 模板渲染。2014 年 2 月首次公开发布的时候这个东西的定位非常克制——不是什么大而全的解决方案就是让视图层写起来舒服一点。这段经历的价值在于它示范了一个可复制的判断方式当你被某个工具烦到的时候先别急着换工具试着问自己我到底要它的哪一部分能力。如果你能把那部分单独拿走、用最小成本用上你就有可能做出一个真正有用的东西。Vue 早期在海外社区也被吐槽过又一个轮子但它在两类场景里迅速扎下根一类是只需要局部增强的老项目另一类是当时的 Laravel 社区这类后端开发者顺手要写前端的群体。这两类人有个共同点他们不想要一套需要专门学习的架构他们想要一个能立刻干活的工具。2. 不跟 Angular、React 硬刚Vue 的技术取舍拆给你看一个框架能活十年靠的绝不是功能比对手多。Vue 在每一个关键岔路口都做了明确的取舍有的地方甚至主动放弃了技术上的优雅。这些取舍背后的逻辑比框架的 API 本身更值得学。2.1 模板语法 vs JSX他为什么死守 HTML 写法这是争议最大的一点。既然 JavaScript 已经能做一切为什么要发明一套模板语法这个问题我被问过无数次。答案其实分两层。第一层是人群覆盖。地球上会写 HTML 的人远多于会熟练写 JavaScript 抽象的人。模板是 HTML 的超集它的学习曲线几乎是平的这直接决定了框架能被多少后端、多少刚入门的人用起来。第二层才是技术层面的关键模板是可被静态分析的。编译器在构建时就能知道哪些节点是静态的、哪些绑定了数据、哪些会随条件变化。所以 Vue 3 编译出来会带上PatchFlag、静态提升hoistStatic、以及v-if分支的缓存运行时 diff 时要比较的节点数量被大幅削减。JSX 因为本质是 JavaScript 表达式自由度更高但编译期能确定的信息也少得多很多优化只能靠运行时扛或者靠额外的编译手段去猜。我给你看一段直观的对比同一个渲染逻辑编译产物差别很大// 模板写法编译器能一眼看出 msg 是唯一的动态部分 // div classstaticspan{{ msg }}/span/div // 编译后大致等价于 import { createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createElementBlock as _createElementBlock } from vue function render(_ctx) { return (_openBlock(), _createElementBlock(div, { class: static }, [ _createElementVNode(span, null, _toDisplayString(_ctx.msg), 1 /* TEXT */) ])) }注意那个1 /* TEXT */的标记它告诉运行时这个 span 里只有文本是动态的。静态的 div 和 class 属性在更新时根本不会被碰。这就是模板换来的东西——不是语法层面的而是性能层面的。我的实际感受是JSX 在高度动态、需要程序化生成结构的场景里更顺手比如渲染一张列数不定的表头、按配置拼装组件树模板在结构相对稳定、以数据绑定为主的业务页面里写起来更快、更不容易写出性能坑。很多人吵这个问题是因为他们默认只能二选一而 Vue 其实两套都给了。2.2 渐进式这三个字救了多少老项目渐进式Progressive是 Vue 最成功的定位没有之一。它的具体含义是你可以只用它的一小部分。一行script src...vue.js/script然后在老页面的某个 div 上挂一个实例这个页面就获得了数据驱动能力。剩下的部分——路由、状态管理、构建工具、服务端渲染——你想用哪个再拿哪个。这个设计对企业项目的意义巨大。我做过好几个祖传 jQuery 页面的改造最省事的方案从来不是重写而是先在新需求模块上挂 Vue稳定跑一个版本之后再往回蚕食。这种局部上船的策略迁移风险低到业务方都没什么感觉。这也是为什么大量中后台系统、内部工具、嵌入式管理页面最后都落在 Vue 上——不是因为它技术最先进而是因为它的进入成本最低。代价当然有。渐进式意味着整个生态是拼装的路由用 vue-router、状态用 Pinia、构建用 Vite每个都得单独学、单独配版本。React 那边虽然也是拼装但社区默认组合相对集中。所以 Vue 项目的技术栈一致性更多时候靠团队规范而不是框架本身约束。2.3 响应式的三次迭代从 defineProperty 到 Proxy到底改了什么面试里被问烂的一道题Vue 2 和 Vue 3 的响应式原理有什么区别大部分人能背出defineProperty 换成了 Proxy但追问一句为什么换就卡住了。我把这个问题拆开讲。Vue 2 用Object.defineProperty递归给对象每个属性装 getter/setter数组则通过改写push、splice等七个方法来实现拦截。这套方案有三个硬伤新增属性、删除属性无法被追踪必须用Vue.set/Vue.delete这是个长期被吐槽的心智负担。数组下标赋值、length修改无法追踪。初始化时要把整个数据对象递归遍历一遍对象越大启动越慢不管这个属性后面用不用。Vue 3 换成Proxy之后拦截的是对对象的操作而不是对某个属性的读写前面三个问题一次性消失新增属性天然可追踪Map、Set这类集合也能支持而且可以实现懒代理——只有真正被访问到的嵌套对象才递归包一层。性能提升不是靠某个黑魔法而是靠少做无用功。原理说清楚之后我建议你亲手写一个三十行的迷你响应式比看十篇分析文章都管用// 极简 reactive effect够你理解依赖收集和派发更新 let activeEffect null function effect(fn) { activeEffect fn fn() // 首次执行触发 get完成依赖收集 activeEffect null } function reactive(target) { const deps new Map() // key - Seteffect return new Proxy(target, { get(obj, key) { if (!activeEffect) return Reflect.get(obj, key) if (!deps.has(key)) deps.set(key, new Set()) deps.get(key).add(activeEffect) return Reflect.get(obj, key) }, set(obj, key, value) { const result Reflect.set(obj, key, value) const set deps.get(key) if (set) set.forEach(fn fn()) // 派发更新 return result } }) } const state reactive({ count: 0 }) effect(() console.log(count is, state.count)) // 收集依赖 state.count // 触发重跑打印 count is 1跑一遍这段代码你对依赖收集副作用派发更新这几个词的理解会立刻落地。之后再去理解 Vue 3 里track/trigger、ref和reactive的区别、computed的惰性求值都是在这套骨架上加东西。至于后续版本里对响应式做的链表化依赖存储、版本计数这类优化公开分享里讲得很清楚核心思路一直是减少不必要的遍历和触发。顺便说一个方向上容易被忽略的事Vapor Mode 这类探索本质是想把虚拟 DOM 这一层也省掉走编译期直接生成精确操作 DOM 的代码。这不代表虚拟 DOM 错了而是场景变了——在大量静态结构、少量动态绑定的业务页面里虚拟 DOM 的运行时开销确实是可以省的。理解为什么现在又不需要它了比记住Vue 用了虚拟 DOM更有价值。3. 开源项目活下去靠的从来不是热情写开源项目的人多如牛毛能把一个框架维护十年、还持续给出大版本演进的屈指可数。中间隔着的不是技术水平是组织、资金和判断力。这一段讲的是尤雨溪最不容易被复制的那部分能力。3.1 从 Meteor 辞职去做全职开源钱从哪来2016 年前后他从 Meteor 离职全职投入到 Vue 上。这件事在当时是非常冒险的——没有公司背书没有大厂实验室养着收入来源主要靠社区赞助Patreon 那一类。这是一个很多人不敢想的决定因为开源维护的现实是这样的写核心代码只占很小一部分时间。大量时间花在处理 issue、回答提问、写文档、发版本、协调贡献者。用户越多抱怨越多而且大部分抱怨带着你必须马上修的语气。我见过太多人做了个两千 star 的库半年后就再也不更新了原因几乎都一样投入产出比崩了。尤雨溪能撑下来除了框架本身被用得多另一个关键动作是把社区组织化——建立核心团队、引入 RFC 流程、让不同的人负责不同模块、把发布节奏固定下来。Vue 的 RFC 仓库是个很好的范例一个重要的 API 变更先写提案、公开讨论、收集反馈再决定要不要合。这套流程让社区感觉我参与了框架的设计也把决策压力从一个人身上分摊了出去。注意如果你自己也在维护开源项目或者公司内部的公共库尽早把我一个人的判断变成一份公开的规则。前者你一旦请假整个项目就停摆后者才能活过你的精力周期。3.2 Vue 3 重写与 Vite 的诞生2020 年那两次豪赌Vue 3 是免费的午餐的反面。重写意味着生态要跟着重排TypeScript 全面重写、Composition API 引入新的代码组织方式、虚拟 DOM 和响应式全换、周边库状态管理、UI 库、构建插件都要跟版本。短期看这是纯粹的给用户添麻烦——无数团队卡在Vue 2 挺好用的为什么要升上。但如果不重写呢defineProperty的天花板、类型系统的缺失、大型项目下的性能瓶颈、以及当时构建工具的启动速度问题都会积累到五年后集中爆炸。我自己的判断是这一步必须走只是时间点选得不算完美——升级路径的平滑程度确实被低估了很多团队因此长期停在 Vue 2直到 Vue 2 官方支持周期结束才被迫迁移那个迁移过程比当年主动升要痛苦得多。紧接着是 Vite。这个项目的切入点特别精准那几年大家最大的日常痛苦就是改一行代码等十几秒。Vite 的解法是开发时直接利用浏览器原生的 ESM 能力只对用到的模块按需编译把依赖用 esbuild 预构建一次生产构建再交给 Rollup 打包。结果是冷启动从几十秒掉到接近瞬时热更新几乎感觉不到延迟。这里有个特别值得学的思维习惯遇到长期存在的普遍痛点时先问是不是我们一直以来的做法本身就有前提假设可以推翻。以前之所以要先打包再开发是因为浏览器不支持模块而这个前提早就变了只是大家的工具链还在沿用旧习惯。这类机会比把某个环节优化 20%值钱得多。3.3 Vue 只适合小项目这句话是怎么被造出来的这个说法流传很广我听过的最离谱的版本是Vue 做不了大型系统。它有一个现实来源上手太容易 门槛太低 大量没受过工程训练的开发者涌入产出了一批没有测试、没有分层、状态乱飞的项目。项目烂了锅被扣到框架头上。我的实际观察是反过来的。我参与过的一个后台系统几十个业务模块、上百个路由、多团队并行开发用的是 Vue 3 TypeScript Pinia 内部组件库配合工作流引擎的流程编排前端复杂度不低但只要状态边界划清楚、组件分层定死、请求层统一封装可维护性一点不比其他栈差。大型项目烂不烂取决于团队有没有工程纪律跟框架姓什么关系不大。真正该反思的是上手快这件事会掩盖团队基本功的缺失。React 用起来麻烦一点反而逼着新人先学抽象和分层Vue 太顺容易让人以为能跑起来就是对的。这也是我给带团队的人的一点建议——如果你们用 Vue一定要在项目初期把工程规范补上因为它不会替你挡住这些事。4. 把他的路径翻译成你自己的前端学习路线聊完故事和决策回到最实际的问题一个普通前端能从这个人身上抄走什么我把答案整理成三段可执行的东西分别对应能力模型、面试准备和职业方向。4.1 三个阶段的能力模型从会写页面到能做取舍我把前端的能力分成三层你可以对照看看自己在哪。阶段典型表现卡点突破方式会写页面拿到设计稿能还原会用组件库遇到没见过的需求就无从下手手写组件弹窗、虚拟列表、表单引擎会设计抽象能封装通用组件、抽公共逻辑、定项目结构抽象过度或抽象不足别人看不懂反复做删掉自己写的抽象练习会做取舍选型、定边界、判断什么时候不要做缺少真实业务压力和复盘主动承担技术方案评审前两层靠练第三层靠经历。尤雨溪的第三层能力是在用 Angular 用得难受、要不要重写 Vue 3、要不要做 Vite这些真实决策里练出来的。普通开发者想在第三层上成长最快的路径不是看更多文章而是去承担一个有真实代价的决定——比如选型选错了要背锅的那种。4.2 面试官问响应式原理其实在考什么现在的前端面试从初中级到高级考点分布其实很稳定。我把常见的几类和它们真正想考的东西列一下响应式 / 渲染原理不是考你能背多少而是考你有没有动手验证过。你写过上面那段三十行的 Proxy 代码回答时的颗粒度完全不一样。编译时优化v-if和v-show的选择、key的作用、静态提升考的是你知不知道框架在替你做什么因为不知道就没法做性能判断。工程化构建配置、环境变量、分包策略、按需加载、体积治理。这块是区分中级和高级的分水岭很多候选人能写业务但不能解释自己的构建产物为什么是两个 G。状态管理与边界什么时候上全局状态、什么时候用 URL 参数、什么时候用请求缓存。这题考的是经验不是知识。场景题大文件上传、长列表卡顿、白屏排查、跨端适配。面试官想听的是你的排查链路不是标准答案。一个实用建议把你做过的每个项目按问题—方案—代价—结果四段式整理成二十来个卡片。面试时遇到类似问题直接调卡片比临场组织语言可靠得多。至于机试和在线笔试最大的坑是题目读太快和边界条件不考虑我见过太多人在字符串处理题上因为没处理空输入直接挂掉——笔试里的分是真金白银别浪费在读题上。4.3 AI 时代前端的出路岗位没消失职责在挪这两年前端是不是要没了的声音特别大。我的判断是纯粹切图、纯粹搬组件的岗位确实在萎缩但前端在 AI 应用里的位置反而在变重要。原因很直接——所有大模型的能力最终都要通过界面交付给人而界面可靠性、流式渲染、状态一致性这些事正是前端的专业领域。具体往哪些方向挪我看到几个明确的机会点流式交互对话式产品的核心是流式输出SSE / WebSocket要处理中断、重试、多路并发、Markdown 实时渲染、代码高亮增量更新。这块的工程复杂度远高于普通表单页面。工具调用的可视化Agent 会调用各种工具前端要把调用链路、中间结果、失败重试清楚地呈现出来。这本质是复杂状态机 可视化前端的老本行。状态可靠性AI 应用特别容易状态错乱比如用户连点两次发送。仔细想想这个问题的本质和重复提交订单是同一类问题——幂等设计、乐观更新回滚、请求去重。前端在这块的积累可以直接迁移过去。工程侧模型输出的不确定性让前端必须更严格地做降级、超时、兜底。这些是纯工程能力AI 帮不了你。所以前端转 Agent 开发这条路我的建议不是丢掉前端去学训练模型而是站在前端的壳里往深走一层把异步、状态、渲染这三件事做到极致再补一点后端和协议层的知识消息队列的幂等、服务端推送的机制你在 AI 产品团队里的不可替代性就出来了。反过来如果你只会调接口、拼页面那确实是危险的位置。5. 我踩过的坑把取舍思维落到真实项目里道理讲完落不到项目里都是空的。下面这三个坑是我自己踩过或者亲眼看着团队踩过的共同点是方向都没错错在没做取舍判断。5.1 组件库Element Plus 能覆盖 80%剩下 20% 才是成本所在用现成组件库起步当然对尤其是中后台。但真正的成本不在用不用而在那 20% 定制需求怎么处理。我见过两种典型翻车方式。一种是扛着改直接改组件库源码或者用一堆深层选择器、::v-deep覆盖样式。升级组件库版本时全线崩没人敢动。另一种是全自研觉得组件库不合口味从按钮开始造半年时间造出一套不如人家的东西业务需求一个没做。我后来稳定下来的做法是三层结构基础层直接用组件库不加任何魔改。中间层做一层薄封装业务无关只统一交互约定比如所有表格的分页参数、所有表单的校验提示位置。业务层再包一次处理真正的业务差异。这样组件库升级只需要改中间层业务代码基本不动。判断要不要自研的标准也很简单如果这个组件在三个以上业务里长得不一样就该自研如果只是样式不一样那叫主题不叫自研。5.2 微前端不是所有中后台都该上 qiankun微前端被吹了很久。我在一个项目里真的用了之后得到的教训很具体。它解决的问题是真问题多个团队维护同一个大后台技术栈不同、发布节奏不同、构建产物互相牵连。但它带来的成本往往被严重低估跨应用的样式污染、路由状态同步、公共依赖版本冲突两个子应用各自打包了不同版本的 Vue、跨应用通信的调试困难、以及最要命的——本地开发环境的搭建复杂度直接翻倍。我的判断标准是这样的场景建议单团队、技术栈统一、模块 10 个以内不要上微前端用路由懒加载 目录规范就够了多团队、发布节奏互不影响、有存量老系统要接入可以考虑但要先定死通信协议和依赖共享策略只是想看起来架构先进千万别如果确定要上我的经验是公共依赖一定要走共享比如通过 externals 统一 CDN 或 import map否则包体积会失控样式一定要隔离沙箱或者前缀约定二选一不要指望自动隔离万无一失子应用之间的通信只允许通过一层明确的事件总线禁止互相 import 业务代码。5.3 那些看着不起眼、出事很致命的前端细节最后这部分是我攒下来的零碎经验都是真出过事的。大文件上传。浏览器主线程一旦被分片计算和哈希占住页面直接卡死。我的做法是把文件切片、计算哈希这些 CPU 密集操作放进 Web Worker主线程只负责状态展示和进度更新。再配合分片并发控制并发数别超过 3和断点续传用户体验会好很多。另外必须处理用户连点两次上传按钮的情况前端要做请求去重和幂等标记这和后端做幂等是一套思路。图片前端压缩。上传前用 Canvas 或createImageBitmap压缩能省下大量带宽和后端存储。但要注意两件事一是方向信息EXIF 里的旋转标记在部分手机上会被丢掉压缩后图歪了二是压缩要放到 Worker 或者按需串行执行否则批量选图时会明显掉帧。大屏自适应。方案不少核心是先定基准设计尺寸再选缩放策略等比例缩放 / rem 换算 / CSS 容器查询。我的教训是别混用最怕的是有人用 rem 做整体缩放又在局部写了固定 px自适应变成了局部错位。数据 Mock。接口没好的时候用 Mock 工具比如基于 Service Worker 的方案能让前端独立推进但一定要定好Mock 数据契约否则接口真上线时字段名对不上返工成本比不 Mock 还高。本地开发环境踩的坑。你一定见过端口被占用依赖锁冲突这类报错本质是多个进程抢同一份资源。在国内网络环境下装依赖慢也会被误判成配置错误。我的习惯是所有项目统一用锁定文件 固定 Node 版本.nvmrc或 engines 字段把环境问题挡在协作之外。再补一句关于技术选型要跟着业务阶段走的体会。早期项目要做的是快速验证选型要的是启动快、上手快中期进入规模化选型要的是可维护性和类型安全后期做多端和性能治理才需要考虑 SSR、编译优化这些重活。我见过太多项目在早期就抄了后期架构结果开发速度被拖垮业务还没验证就先被架构拖死了。尤雨溪把 Vue 做成渐进式本质上就是这个道理——不同阶段用不同深度别一步到位。我自己用 Vue 和 Vite 这么多年最有价值的一课不是某段源码而是他反复展现的那种做法先把问题定义清楚再选一个能覆盖 80% 场景的方案剩下的 20% 用约定和文档兜住然后坦然接受这个方案带来的代价。这套做法放在框架设计上叫渐进式放在你手上的业务项目里叫别过度设计也别裸奔。