Skip to content

前言

写作动机

凌晨一点。窗外的北京三环还有零星车流,屏幕上是 Vue DevTools 的 Timeline 面板。

我正在排查一个诡异的性能问题——一个看似简单的 computed 属性,却触发了整条组件树的重新渲染。我点开 DevTools 的响应式依赖图,沿着依赖链一层层追踪下去。当我最终定位到根因时,我愣住了。

不是因为找到了 Bug。而是因为我看到了一幅令人屏息的画面:

一个 ref 的变更,像石子投入湖面,涟漪精确地扩散到每一个依赖它的 computed,再到每一个消费这些 computed 的组件——没有多余的一次渲染,没有遗漏的一次更新。每一条依赖边都是精确的、最小化的、可预测的。

那不是一个"还不错"的响应式系统。那是一台精密的因果传播机器。

我打开 Vue 3.6 的源码,从 packages/reactivity/src/effect.ts 第一行读起。两个小时后,我发现自己看到的已经不是我熟悉的那套响应式实现了——Set-based 的依赖追踪消失了,取而代之的是一套基于版本计数(version counting)的全新架构。没有 Set,没有 cleanup,没有每次求值都要重建依赖集合的开销。

这就是 Alien Signals——Vue 3.6 响应式系统的第三次重写。

我合上笔记本,揉了揉眼睛,心里只有一个念头:

这套东西值得被认真讲一遍。不是教程式的"怎么用",而是源码级的"为什么"。

为什么在 Vue 3.6 / Vapor Mode 时代写这本书

2024 到 2026 年间,前端框架的竞争格局发生了根本性的位移。

React Server Components 模糊了客户端与服务端的边界。Svelte 5 的 Runes 用编译器魔法消灭了运行时的响应式开销。Solid.js 用细粒度响应式证明了"没有虚拟 DOM"不仅可行,而且更快。Angular 引入了 Signals,宣告了自己向响应式范式的转身。

而 Vue,在这场军备竞赛中,做了两件足以改写历史的事:

第一,Vapor Mode——彻底抛弃虚拟 DOM。

Vapor Mode 不是对模板编译的又一次优化。它是对 Vue 底层渲染范式的根本重构。在 Vapor 模式下,模板不再编译为返回虚拟节点树的 render 函数,而是编译为直接操作真实 DOM 的命令序列。没有 VNode,没有 patch,没有 diff——编译器在编译期就确定了哪些节点是静态的、哪些绑定是动态的,生成的代码只做最小量的精确更新。

第二,Alien Signals——响应式系统的第三次重写。

从 Vue 3.0 的 @vue/reactivity(基于 Set 的依赖追踪),到 Vue 3.5 的优化版(引入双向链表),再到 Vue 3.6 的 Alien Signals(基于版本计数的全新架构),每一次重写都不是"修修补补",而是对响应式核心模型的重新思考。

这两件事加在一起,意味着一个关键事实:

如果你的 Vue 源码知识停留在 3.4 或更早,你实际上在学习一个已经被替换的系统。

市面上的 Vue 源码书籍,绝大多数基于 Vue 3.0–3.4 版本。它们讲的是基于 Set 的依赖追踪、基于 VNode 树的 patch 算法、基于 Block Tree 的编译优化。这些知识并非没有价值——理解"旧系统为什么被替换"本身就是一种深刻的学习。但如果你想理解今天的 Vue 实际上在做什么,你需要一本基于 Vue 3.6 的书。

这本书就是为这个时刻而写的。

Alien Signals 重写响应式意味着什么

让我用一个类比来解释 Alien Signals 为什么重要。

想象你管理一座城市的供水系统。传统方案(Vue 3.0–3.4 的 Set-based tracking)是这样工作的:每次打开水龙头,系统记录下"这个水龙头正在使用水源 A"。当水源 A 的水质变化时,系统遍历所有记录,找到所有正在使用水源 A 的水龙头,逐一通知。每次水龙头关闭再打开,之前的记录被清除,重新建立。

这套系统是正确的,但有两个问题:第一,每次重新建立记录需要分配内存(new Set());第二,清除旧记录本身也有开销(Set.delete())。当城市规模扩大——数千个水龙头、数百个水源——这些开销就变得不可忽视了。

Alien Signals 的方案截然不同。它不记录"谁在使用谁"。它给每个水源贴一个版本号。每次水质变化,版本号加一。每个水龙头只需要记住"我上次看到的版本号是多少"。当它需要出水时,比较当前版本号与记忆中的版本号——如果不同,说明水质变了,需要更新;如果相同,什么都不用做。

没有集合的分配与回收。没有遍历的开销。版本比较是 O(1) 的整数操作。

这不仅仅是"优化"。这是响应式模型的范式转换——从基于集合的订阅-通知模型基于版本的惰性求值模型

🔥 深度洞察

Alien Signals 的版本计数策略,本质上是将"推模型"(Push:数据变了就通知所有依赖者)转化为"拉模型"(Pull:只有在需要求值时才检查数据是否变了)。这一转变的哲学意义在于:最快的通知是不通知。 如果一个 computed 的值在当前 tick 内没人读取,它根本不需要重新计算——即使它的依赖已经变了一百次。这就是惰性求值的力量:只为真正被使用的值买单。

量化来说,Vue 团队的基准测试表明:

指标Vue 3.4(Set-based)Vue 3.6(Alien Signals)提升
响应式对象创建基准~-40% 内存显著
依赖追踪开销每次求值重建 Set版本号比较 O(1)数量级
大规模依赖图遍历O(n) 遍历 + Set 操作O(1) 版本比较 + 按需传播显著
GC 压力高(频繁创建/销毁 Set)极低(无临时对象分配)质变

本书与其他 Vue 书的区别

如果你在书店或网上搜索"Vue 源码"相关书籍,大致会看到三类:

类别典型内容读完之后你会…
API 实战书组件开发、Pinia 状态管理、Vue Router 使用、项目实战能熟练使用 Vue,但不知道底层发生了什么
早期源码书Vue 3.0–3.4 源码解析、Set-based 响应式、VNode + Patch 算法理解旧版实现,但面对 3.6 的新架构会感到陌生
本书基于 Vue 3.6 源码,覆盖 Alien Signals、Vapor Mode、编译器全链路理解 Vue 当前的设计、演进的动力、未来的方向

区别的核心在于:其他书基于已经被替换的实现,本书基于正在运行的现实

这不是一次增量更新——从 Set-based 到 version counting 是响应式模型的范式转换,从 VNode-based 到 Vapor 是渲染模型的范式转换。用旧范式的知识去理解新系统,不仅效率低下,而且可能导致根本性的误解。

教科书给你答案。源码给你问题——以及回答这些问题的完整思考过程。

本书的承诺是:带你看到 Vue 3.6 每个设计决策背后的"为什么",看到被放弃的替代方案,厘清每一处权衡的得与失。 无论你是否选择深入 Vue 的源码,这些响应式系统设计、编译器架构、渲染优化的经验,都可以直接迁移到你对任何前端框架的理解中。

本书读者

这本书为五类读者而写:

高级前端工程师——你已经熟练使用 Vue,但想知道 v-model 的双向绑定在编译期做了什么、<Suspense> 的异步边界如何管理 pending 状态、<Teleport> 如何跨越组件树的物理边界。本书提供的源码级解析,让你从"知其然"跨越到"知其所以然"。

框架开发者与架构师——无论你在构建自己的框架还是选型评估,Vue 3.6 的 Vapor Mode 编译策略和 Alien Signals 响应式架构都是业界前沿的设计参考。每章包含与 React、Svelte、Solid.js 的横向对比,帮你在全景中定位每个设计选择。

开源贡献者——不仅知道代码在哪里,更理解它为什么这样写。读懂 Vue 核心团队的设计意图,才能写出高质量的 PR。

技术面试备战者——"Vue 的响应式原理是什么"是高频面试题,但能精确回答 Alien Signals 版本计数机制的候选人,凤毛麟角。本书给你的不是背诵材料,而是深入到可以自信应对任何追问的理解深度。

学生与研究者——每章包含系统性的设计分析,可作为论文引用和研究参考。每章末尾的思考题覆盖概念理解、实践应用和开放讨论三个层次。

不适合的读者:如果你在寻找一本"Vue 3 快速上手"的入门书,这不是。本书假设读者已具备 Vue 使用经验和 TypeScript 基础,想深入理解框架内部的设计与实现。

阅读路线图

本书支持多种阅读方式。你可以从第 1 章顺序通读,也可以根据自身需要选择快速路径:

路径章节适合
快速精华前言 → 1 → 3(响应式核心) → 10(Vapor)时间有限,3 小时获取 80% 架构洞察
响应式深潜1 → 3 → 4 → 5 → 6想彻底搞懂 Alien Signals 的每个细节
编译器之旅1 → 11 → 12 → 13 → 10对模板编译和 Vapor 编译感兴趣
全栈通读1 → 2 → 3 → … → 13系统性通读,建立完整认知
面试突击1 → 3 → 9(diff) → 10(Vapor)聚焦高频考点,快速建立深度

工程师建议顺序通读,每章旁边打开 Vue 源码,边读边探索。急性子直接翻到第 3 章,从 Alien Signals 的第一行代码开始。

源码与约定

本书基于 Vue 3.6.x 版本(具体以各章标注的 commit hash 为准)。核心架构模式演化缓慢——即使代码持续迭代,书中的设计思想仍然适用。

代码约定

所有代码示例均从 Vue 源码中提取,标注对应的文件路径。部分代码为可读性做了适度简化,遵循以下约定:

  • 省略号 // ...:省略与当前讨论无关的代码
  • 注释 // ← 关键:标注当前讨论的核心逻辑
  • TypeScript:所有示例使用 TypeScript,与 Vue 源码保持一致
  • 简化导入:省略明显的 import 语句,避免视觉噪音

源码仓库

git clone https://github.com/vuejs/core.git
cd core
git checkout v3.6.0  # 切换到本书对应版本
pnpm install

建议在阅读每章时,始终在编辑器中打开对应的源码文件。源码是本书最重要的"配图"。

配套资源

致谢

最深的谢意,献给 尤雨溪(Evan You) 和所有 Vue 核心团队成员。本书中剖析的每一个设计决策,都凝结着一线框架作者在真实约束下反复权衡的智慧。从 Vue 2 的 Object.defineProperty 到 Vue 3 的 Proxy,再到 Alien Signals 的版本计数——每一次重写都不是推翻重来,而是在更深层次上回答同一个问题:如何让数据驱动视图的过程尽可能高效、可预测、易于理解?

感谢 Johnson Chu(Alien Signals 的作者)。他对响应式系统的深入思考,将"版本计数"这一看似简单的想法锻造为一套完整的、经过数学证明的依赖追踪架构。

感谢 TypeScript、Vite 和整个前端开源生态。Vue 站在巨人的肩膀上——从 Rollup 到 esbuild,从 Babel 到 SWC,每一层工具链都是无数开发者无偿贡献的结晶。

感谢我的家人。写书的无数个深夜,是他们的理解与支持让我能够心无旁骛地沉浸在源码与架构的世界里。

感谢你,读者。在短视频与碎片信息的时代,选择一本源码级技术书籍,本身就是一种价值声明——你相信深度理解的力量,相信底层原理永远不会过时。你翻开这本书的那一刻,就已经和我站在了同一边。

我们正处于前端框架从"运行时竞赛"迈向"编译期竞赛"的关键拐点。Vapor Mode 不仅仅是 Vue 的一次技术升级——它代表着整个前端行业对"虚拟 DOM 范式"的重新审视。回望历史,2024–2026 或许会被铭记为前端的"编译器觉醒时刻"——正如 React Hooks 重新定义了组件的逻辑组织方式,Vapor Mode 正在重新定义组件的渲染执行方式。

好的代码会被重写,好的架构会被传承,好的设计思想永不过时。

这本书不教你写组件——它教你理解组件背后的整个系统。

这本书献给每一个在深夜读源码的人。


杨艺韬 2026 年春,北京

基于 VitePress 构建