手写一个最小可运行的 Vue3,用来理解它内部是怎么跑起来的——响应式系统、运行时(虚拟 DOM diff / 组件化)、以及把模板编译成渲染函数的编译器。
按照 Vue3 自己的分包方式拆成多个 package,每一块都只保留「核心主线」,去掉工程细节,方便对照源码阅读。
mini-*源码学习系列的一员。Talk is cheap,read the code。
packages/
├── reactivity/ # 响应式:reactive / ref / computed / effect + 依赖收集
├── runtime-core/ # 运行时核心:组件、vnode、render、diff(patch)、slots、emit、provide/inject、nextTick
├── runtime-dom/ # 平台层:把 runtime-core 接到真实 DOM(createElement / patchProp / insert)
├── compiler-core/ # 编译器:template → AST → transform → 渲染函数代码
├── shared/ # 跨包共用的工具函数
└── vue/ # 总出口,re-export 各包;examples/ 下是可运行示例
三块核心能力,对应 Vue 的三条主线:
| 模块 | 它解决什么 | 关键实现 |
|---|---|---|
| reactivity | 数据变了怎么自动重新计算 | reactive(Proxy)、ref、computed(lazy + 缓存)、effect(依赖收集 + scheduler)、readonly / shallowReadonly |
| runtime-core | 组件和虚拟 DOM 怎么挂载、更新 | createVNode / h、render、双端 + 最长递增子序列的 keyed diff、slots、emit、provide / inject、nextTick 调度 |
| runtime-dom | 怎么落到真实 DOM | createRenderer 的 DOM 适配:元素创建、属性 / 事件 patch、insert / remove |
| compiler-core | 模板字符串怎么变成渲染函数 | parse(插值 / 元素 / 文本)→ transform(可插拔节点转换)→ codegen |
依赖用 pnpm(仓库是 pnpm workspace):
pnpm install跑测试(响应式、编译器、watch 都有用例):
pnpm test # vitest跑示例:先 build 出产物,再用任意静态服务器打开 packages/vue/examples/<示例>/index.html:
pnpm build # rollup 打包到 packages/vue/dist
npx serve packages/vue/examples/helloworld # 或任意静态服务器packages/vue/examples/ 下有十几个示例,分别演示 helloworld、组件更新、emit、slot、provide/inject、nextTick、自定义渲染器、模板编译等。
已实现:响应式全套、组件挂载与更新、keyed diff、slots、emit、provide/inject、nextTick、watchEffect、生命周期钩子(onBeforeMount / onMounted / onBeforeUpdate / onUpdated)、基础模板编译(插值 / 元素 / 文本)。
为聚焦核心,以下暂未实现(也是后续可完善方向):完整 watch(带 source/options)、卸载相关钩子(onUnmounted)、模板指令(v-if / v-for / 属性与事件解析)、computed setter、数组方法的响应式追踪。
手写主流框架 / 工具的最小可运行实现,每个仓库只追「核心主线」,不堆功能。
| 仓库 | 内容 |
|---|---|
| mini-vue(本仓库) | 手写 Vue3:响应式 / runtime / 编译器 |
| mini-react | 手写 React:Fiber / reconciliation / Hooks |
| mini-koa | 手写 Koa:中间件洋葱模型 / context |
| mini-webpack | 手写 webpack:依赖图 / loader / plugin |
| mini-compiler | 手写 the-super-tiny-compiler:词法 / 语法 / 转换 / 生成 |
| ts-axios | 手写 axios(TypeScript 版) |
Talk is cheap. Read the code.