梳理响应式系统为什么重构,及如何从 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 里最关键的三个模块串起来:

  • 响应式:实现 refreactiveeffectcomputed
  • 编译时:实现基础模板解析、转换和代码生成
  • 运行时:实现 hrender、组件更新、调度器

最后目标是得到一个可以跑通核心流程的 Vue MVP

这个 MVP 不会覆盖 Vue 的全部能力,也不会追求完整兼容。但它需要能说明一件事:

模板是如何变成渲染函数的,渲染函数如何生成 vnode,vnode 如何挂载到页面,响应式数据变化后又如何驱动组件重新渲染。

Alien Signals 会是这个系列的第一条主线。因为响应式系统是 Vue 运行时更新的入口

实现路线

  1. 使用 monorepo 拆分模块
  2. 使用 esbuild 做构建
  3. 使用单元测试描述每个能力的用例
  4. 每一章只实现一个明确的小目标
  5. 尽量保留 Vue 源码里的关键概念,但删掉和当前目标无关的边界处理

目录会分成这样:

packages/
  reactivity/
  runtime-core/
  runtime-dom/
  shared/

第一阶段会只关注 reactivity

  1. 实现最小版本的 effect
  2. 引入链表结构
  3. 实现 ref 和依赖收集
  4. 实现 reactive 和属性级追踪
  5. 实现 computed 的缓存与脏值判断

等响应式核心跑通之后,再进入运行时和编译时。

参考