梳理响应式系统为什么重构,及如何从 0 实现一个 Vue MVP
2025-09-14 13:17:28
Alien Signals 是什么
在 Vue core 的 #10397 中,响应式系统被重构为基于两个关键设计:
version counting- 双向链表形式的依赖追踪结构
可以粗略理解为:以前更关注“这个 dep 里有哪些 effect”
重构后更关注“dep、subscribe、link 之间如何建立稳定且可清理的连接”
官方 PR 中给了一个很直观的内存对比:在 1000 refs + 2000 computeds + 1000 effects 的测试场景下,相关实例的内存占用从
1426k 降到 631k,约减少 56%。
性能方面,单个 ref 触发多个 effect、读取多个失效的 computed 等场景也有比较明显的提升。
这个系列要做什么
这次不打算只写一个简化版响应式 demo。
我想从响应式开始,一步一步把 Vue 里最关键的三个模块串起来:
- 响应式:实现
ref、reactive、effect、computed - 编译时:实现基础模板解析、转换和代码生成
- 运行时:实现
h、render、组件更新、调度器
最后目标是得到一个可以跑通核心流程的 Vue MVP。
这个 MVP 不会覆盖 Vue 的全部能力,也不会追求完整兼容。但它需要能说明一件事:
模板是如何变成渲染函数的,渲染函数如何生成 vnode,vnode 如何挂载到页面,响应式数据变化后又如何驱动组件重新渲染。
Alien Signals 会是这个系列的第一条主线。因为响应式系统是 Vue 运行时更新的入口
实现路线
- 使用
monorepo拆分模块 - 使用
esbuild做构建 - 使用单元测试描述每个能力的用例
- 每一章只实现一个明确的小目标
- 尽量保留 Vue 源码里的关键概念,但删掉和当前目标无关的边界处理
目录会分成这样:
packages/
reactivity/
runtime-core/
runtime-dom/
shared/
第一阶段会只关注 reactivity:
- 实现最小版本的
effect - 引入链表结构
- 实现
ref和依赖收集 - 实现
reactive和属性级追踪 - 实现
computed的缓存与脏值判断
等响应式核心跑通之后,再进入运行时和编译时。