性能优化
源码体积
1、移除一些冷门的功能(filter、inline-template 等)
2、引入tree-shaking 技术,减小打包体积。原理:依赖ES2015 模块语法的静态结构(import 和export),通过编译阶段的静态分析,找到没有导入的模块并打上标记,然后在压缩阶段通过terser 等webapck 插件删除已标记的代码。
数据劫持优化
Proxy API 并不能侦听到内部深层次的对象变化,因此Vue3 的处理方式是在Proxy 处理器对象的getter 中递归响应。这样做的好处是,只有真正访问到的内部对象才会变成响应式,而不是无脑递归,在一定程度上提升了性能。
编译优化
模板template 编译生成render 函数的流程是可以借助vue-loader 在webpack 编译阶段离线完成,并非一定要在运行时完成。
Vue3 通过在编译阶段优化编译的结果,来实现运行时patch 过程的优化。
Vue3 通过天意阶段对静态模板的分析,编译生成了Block Tree。Block Tree 是将模板基于动态节点指令切割的嵌套区块,每个区块内部的节点结构是固定的,而且每个区块只需要以一个Array 来追踪自身包含的动态节点。
借助Block Tree,Vue3 将node 的更新性能由与模板整体大小相关提升为与动态内容的数量相关。
重写diff 算法。
【API 层面】
- Composition API - 便于代码复用
- SFC Composition API Syntax Sugar(
- Teleport 传送门 - 允许组件渲染在别的元素内,主要开发弹窗组件的时候特别有用
- Fragments 片段 - vue 3 组件不在要求有一个唯一的根节点,清楚了很多无用的占位div
- Suspense - 异步组件,更方便开发有异步请求的组件
- Emits Component Option
- createRender API from @vue/runtime-core to create custom renders
- SFC State-driven CSS Variables(v-bind in )
- SFC can now include global rules or rules that target only slotted content
【工程化工具】
- vite - 更丝滑的开发体验,通用的工程化工具
【框架层面】
更快 -
- 虚拟DOM 重写
- 编译器优化:静态提升、patchFlags、block等
- 基于Proxy 的响应式系统
虚拟DOM
Vue 3 新策略将vdom 更新性能与模板大小解耦,变为与动态节点的数量相关,整体比vue 2 性能提升2-5 倍
【Vue 2 中vdom 性能瓶颈】
- 虽然vue 能够保证触发更新的组件最小化,但单个组件部分变化需要遍历该组件的整个vdom 树
- 传统Odom 性能跟模板大小正相关,跟动态节点的数量无关
【Vue 3 优化工作】
- 将AST 基于动态节点指令(if/for/slot)切割为嵌套的区块,更新一个块内节点的时候,就不需要递归遍历树,可以跟踪平面的数组了。执行开销小了一个数量级。
- 使用编译器Complier 主动监测模板中的静态节点,将其提升到render 函数之外,避免在每次渲染时都重新创建对象,提高对内存使用率、减少垃圾回收频率。
- 给元素一个追踪标记,无论层级嵌套多深,更新时可以直接遍历动态节点
1、diff 方法优化
Vue 2.x 中的虚拟DOM 是进行全量的对比。Vue3 中新增了静态标记(patchFlag):在与上次虚拟节点进行对比的时候,只对比带有patchFlag 的节点,并且可以通过flag 的信息得知当前节点要对比的具体内容。
2、hoistStatic 静态提升
Vue2 中无论元素是否参与更新,每次都会重新创建。vue3 中对不参与更新的元素,只会被创建一次,之后会在每次渲染时候被不停复用。
3、cacheHandlers 事件侦听器缓存
默认情况下onClick 会被视为动态绑定,所以每次都会去追踪它的变化,但是因为是同一个函数,所以没有追踪变化,直接缓存起来复用即可。
更小 - 更好的tree shaking(摇树)优化,提供了更多的内置功能
【Vue 2 现有限制】
并不是每个人都使用框架的所有功能,但仍需下载/解析相应代码
【Vue 3 优化】
将大多数全局API 和内部组件移至ES模块导出,tree-shaking 更友好
更容易维护 - TS + 模块化
更容易扩展 -
- 独立的响应式模块
- 自定义渲染器
【原理】
体验编译器优化
Reactive 实现
【参考资料】 《vue.js 技术内幕》