介绍
- 源码采用 monorepo 方式进行管理,将模块拆分到package目录中
- Vue3 采用ts开发,增强类型检测。 Vue2 则采用flow
- Vue3 的性能优化,支持 tree-shaking, 不使用就不会被打包
- Vue2后期引入RFC , 使每个版本改动可控 rfcs
内部代码优化
- Vue3 劫持数据采用proxy ,vue2 劫持数据采用 defineProperty, defineProperty 有性能问题和缺陷
- Vue3 中对模块编译进行了优化,编译时生成了 Block tree, 可以对子节点的动态节点进行收集,可以减少比较,并且采用 patchFlag 标记动态节点
- Vue3 采用 compositionApi 进行组织功能,解决反复横跳,优化复用逻辑(mixin带来的数据来源不清晰,命名冲突等)相比 optionsApi 类型推断更加方便
- 增加了Fragment, Teleport, SusPense组件
Vue3 架构分析
1.Monorepo介绍
Monorepo 是管理项目代码的一个方式,指在一个项目仓库(repo)中管理多个模块/包(package)
- 优点:
- 一个仓库可维护多个模块,不用到处找仓库
- 方便版本管理和依赖管理,模块之间的引用,调用都非常方便
- 缺点:
- 仓库体积会变大
2.Vue3项目结构
├─packages # N个repo
│ └─compiler-core # 与平台无关的编译器核心
│ └─compiler-dom # 针对浏览器的编译模块
│ └─compiler-sfc # 针对单文件解析
│ └─compiler-ssr # 针对服务端渲染的编译模块
│ └─reactivity # 响应式系统
│ └─runtime-core # 与平台无关的运行时核心 (可以自定义渲染器)
│ └─runtime-dom # 针对浏览器的运行时。包括DOM API,属性,事件处理等
│ └─runtime-test # 用于测试
│ └─server-renderer # 用于服务器端渲染
│ └─shared # 多个包之间共享的内容
│ └─size-check # 用来测试代码体积
│ └─template-explorer # 用于调试编译器输出的开发工具
│ └─vue # 完整版本,包括运行时和编译器
+---------------------+
| |
| @vue/compiler-sfc |
| |
+-----+--------+------+
| |
v v
+---------------------+ +----------------------+
| | | |
+-------->| @vue/compiler-dom +--->| @vue/compiler-core |
| | | | |
+----+----+ +---------------------+ +----------------------+
| |
| vue |
| |
+----+----+ +---------------------+ +----------------------+ +-------------------+
| | | | | | |
+-------->| @vue/runtime-dom +--->| @vue/runtime-core +--->| @vue/reactivity |
| | | | | |
+---------------------+ +----------------------+ +-------------------+
3.安装依赖
依赖 | 说明 |
---|---|
typescript | 支持ts |
rollup | 打包工具 |
rollup-plugin-typescript2 | rollup 和 ts的 桥梁 |
@rollup/plugin-node-resolve | 解析node第三方模块 |
@rollup/plugin-json | 支持引入json |
execa | 开启子进程方便执行命令 |
必须使用yarn
yarn init -y
yarn add typescript rollup rollup-plugin-typescript2 @rollup/plugin-node-resolve @rollup/plugin-json execa -D
Running this command will add the dependency to the workspace root rather than the workspace itself, which might not be what you want - if you really meant it, make it explicit by running this command again with the -W flag (or —ignore-workspace-root-check
tsc --init
4.目录结构:
├─packages # N个repo
│ └─reactivity # 响应式目录
│ │ package.json
│ └─src
│ index.ts
│ └─shared #公共方法目录
│ │ package.json
│ └─src
│ │ index.ts
└─scripts # 打包命令
│ │ build.js # 全部打包
| | dev.js # 单个打包
│ package.json # 配置运行命令
│ rollup.config.js # rollup配置文件
│ tsconfig.json # ts配置文件 更改为esnext
│ yarn.lock
5.代码文件
- package.json
- packages/reactivity/package.json
- packages/shared/package.json
- scripts/build.js
- scripts/dev.js
- rollup.config.js
- tsconfig.json
注意:在某个模块下引入另一个模块时,需要配置 tsconfig.json
import {shared} from "@vue/shared"
//找不到模块“@vue/shared”。
//你的意思是要将 "moduleResolution" 选项设置为 "node",还是要将别名添加到 "paths" 选项中
const reactivity = {}
export {
reactivity
}
"moduleResolution":"node",
"baseUrl":".",
"paths": {
"@vue/*":[
"packages/*/src"
]
}
搭建好后执行的命令:
"dev": "node scripts/dev.js",
"build": "node scripts/build.js"
参考: