前言
整体设计思想
- 模块拆分,Vue3中模块与模块之间
耦合度较低
,可以独立使用
。 - 按需引入,再配合构建工具的
tree-shaking
,可以大幅度减少打包体积
。 - 重写API
- 自定义渲染器,扩展能力强。
- 虚拟Dom思想,比较新旧虚拟节点,找到变化再更新
diff
- 区分编译时和运行时
- 编译时:模板语法 => render函数 => 虚拟DOM
- 运行时:将虚拟DOM转为真实DOM
- 采用typescript开发
- 依然保留vue2的逻辑
Vue3&Vue2对比
- 源码架构
- vue3:更注重模块的拆分,源码采用
Monorepo
的方式管理,将模块拆分到package
目录下,各模块自成一个npm包,模块间耦合度低,模块可独立使用。 - vue2:源码处于同一个包中,后续迭代时只能在其基础上开发,如
weex、mp-vue
,代码结构冗余。
- vue3:更注重模块的拆分,源码采用
- 类型检测选择:
- vue3:TS,代码提示强,强类型检测。
- vue2:flow,有些类型无法推断出来。
- 性能:
- vue3:全ESModule开发,支持
tree-shaking
,代码打包体积较好。 - vue2:配置生成文件,无法准确推断模块是否使用。
- vue3:全ESModule开发,支持
- API
- Vue3:composition-api
- Vue2:option-api
- 渲染器
- Vue3:自定义渲染器,扩展能力强。
- Vue2:统一渲染器
- 开发方式
- Vue3:ts+ESModule
- Vue2:js+传统模块化
Vue3代码优化
- Vue3采用
Proxy
替代Vue2的defineProperty
。defineProperty
的缺陷:遍历对象所有属性、新增删除属性无法监听到。
- 模板编译优化
- 编译时生成
Block tree
,可以对动态节点进行收集,可以减少比较,并且采用patchFlag
标记动态节点。
- 编译时生成
- 采用
CompositionApi
组织功能- 解决反复跳转开发,优化复用逻辑(mixin带来的数据源不清晰、命名冲突问题)。
- 相比OptionApi,类型推断更方便。
- 增加了
Fragment、Teleport、Suspense
等组件。
Vue3架构
环境区分
- Vue将代码运行环境区分为
运行时
和编译时
,也有运行时+编译时
。 - 对于开发者而言:
- 运行时只能执行使用
render
渲染虚拟节点。 - 编译时只能通过
template
将模板编译成render
才能运行。 - 默认开发时是
运行时+编译时
的环境。 - 生产环境可以只部署编译时的代码,减少编译体积。
- 运行时只能执行使用
Monorepo架构
简介
- 是管理项目代码的一种
思路/方式
,指在一个项目仓库 (git-repo
) 中管理多个模块/包 (npm-package
),不同于常见的每个模块建一个git-repo
。 - 目前不少大型开源项目采用了这种方式,如
Babel、React、Vue
等。monorepo
管理代码只要搭建一套脚手架,就能管理(构建、测试、发布)多个package
。 - 在前端使用角度来看,
monorepo
就是把多个工程放到一个git
仓库中进行管理,因此他们可以共享同一套构建流程、代码规范也可以做到统一,特别是如果存在模块间的相互引用的情况,查看代码、修改bug、调试等会更加方便。 Monorepo
里面的每个功能模块,则是像我们玩的乐高积木一样,有标准的接口,即使从这个项目中拆离出去,也能使用。- pnpm&monorepo
优点
- 代码复用非常简单【共用公共依赖】
- 简化依赖管理【同级目录方便相互引用】
- 原子提交能让重构全局特性更容易【一个git】
- 跨组合作更方便【各依赖间无逻辑关联性,只有引用关联】
pnpm
- 一个较新的包管理工具,通过软硬连接的方式共用相同的依赖。
- 优点:
- 减小依赖包体积,且下载过的包会被缓存至本地磁盘,二次下载更快。
- 更加优雅的处理幽灵依赖的问题(依赖A的依赖B被直接使用,若后续依赖A不再使用依赖B,则项目报错)。
- 缺点:需要定时清空磁盘中的缓存依赖,避免过大。
- 优点:
Vue3中的Monorepo环境
- 基于
pnpm
搭建的Monorepo
项目仓库。 - 搭建思路
- 初始化
pnpm init -y
- 配置公共目录(workspace)。
- 新建npm配置文件
.npmrc
,配置幽灵依赖删除。
-
// .npmrc // 幽灵依赖--将依赖A中的依赖同步到node_module下,避免以后依赖A中的依赖发生改变,导致无法察觉的bug shamefully-hoist = true
- 在公共目录下新增子仓库(packages下)
- 初始化子仓库,则子仓库们可共用相同的依赖,且有自己的依赖,且两两解耦。
- 初始化
Vue3组成与架构一切基于组件
- reactivity :
核心包,响应式系统
- runtime-core :与平台无关的运行时核心(
扩展包,可根据平台扩展出对应的API,自定义渲染器
)。createRenderer
:根据平台使用核心包core
,创建出对应的渲染器render
render
-- 渲染器把接收到的虚拟DOM,转换成真实DOM并渲染至宿主元素
- 本质是使用
patch
- 本质是使用
createApp
:createApp(render,hydrate)
-- 创建实例hydrate
--SSR
,服务端直接将vnode生成为一个html
- runtime-dom :针对浏览器的运行时。包括
DOM API
,属性,事件处理等。 runtime-test
:用于测试;server-renderer
:用于服务器端渲染;- compiler-core :与平台无关的编译器核心;
- compiler-dom :针对浏览器的编译模块;
compiler-ssr
:针对服务端染的编译模块;compiler-sfc
:针对单文件解析;size-check
:用来测试代码体积template-explorer
: 用于调试编译器输出的开发工具- shared :多个包之间共享的内容
- vue :完整版本包括运行时和编译器
环境搭建
-
搭建monorepo[模块共享]
1. pnpm init -y 2. mkdir packages 3. vi .npmrc 4. pnpm install vue -w 1. -w => workspace
-
搭建环境
pnpm install
- ts => typescript
- es => esbuild[速度很快的es模块转换]
- 获取命令行参数框架 => minimist
- scripts/*
-
图例: