Skip to content

vue3 中 treeShaking 的特性

介绍

Tree shaking 是一种通过清除多余代码方式来优化项目打包体积的技术,专业术语叫 Dead code elimination

简单来讲,就是在保持代码运行结果不变的前提下,去除无用的代码

如果把代码打包比作制作蛋糕,传统的方式是把鸡蛋(带壳)全部丢进去搅拌,然后放入烤箱,最后把(没有用的)蛋壳全部挑选并剔除出去

而 treeshaking 则是一开始就把有用的蛋白蛋黄(import)放入搅拌,最后直接作出蛋糕

也就是说 ,tree shaking 其实是找出使用的代码

在 Vue2 中,无论我们使用什么功能,它们最终都会出现在生产代码中。主要原因是 Vue 实例在项目中是单例的,捆绑程序无法检测到该对象的哪些属性在代码中被使用到

js
import Vue from 'vue'

Vue.nextTick(() => {})

而 Vue3 源码引入 tree shaking 特性,将全局 API 进行分块。如果您不使用其某些功能,它们将不会包含在您的基础包中

js
import { nextTick, observable } from 'vue'

nextTick(() => {})

vue2 不支持的原因

vue2 的设计和构建是基于 ES5 时代完成,大多数功能和组件是以对象的形式暴露出来的,而且整个库的组织方式和设计没有针对 Tree-shaking 这种高级的代码优化进行特别的优化

  • ES5 构建: Vue 2 的构建版本基于 ES5 ,它不太支持按需引入

  • 组件导入方式: 在 Vue 2 中,大部分组件是通过直接引入 Vue 对象的属性来使用的,这导致整个 Vue 对象以及所有的属性都会被包含进最终的构建中,无法精确地按需引入

  • 组件间关系: Vue 2 组件在定义和使用时的关系较为复杂,可能会造成不同组件之间的依赖关系和引用关系,这也会影响 Tree-shaking 的效果

vue3 中为了适配 vue2 的 option Api 编写了大量的兼容代码,因而当我们在代码中不再使用 options 的 API,就可以通过一个叫做__VUE_OPTIONS_API__的特性开关去关闭这个特性,这样最终打包的 Vue 代码就不会包含这部分,进而减少代码体积,⚠️ 禁用此功能将减小打包结果的体积,但如果第三方库依赖选项式 API,则可能影响兼容性

总结

Tree shaking 是基于 ES6 模板语法(import 与 exports),主要是借助 ES6 模块的静态编译思想,在编译时就能确定模块的依赖关系,以及输入和输出的变量

Tree shaking 无非就是做了两件事:

  • 编译阶段利用 ES6 Module 判断哪些模块已经加载
  • 判断那些模块和变量未被使用或者引用,进而删除对应代码

通过 Tree shaking,Vue3 给我们带来的好处是:

  • 程序体积更小(更小)
  • 程序执行时间更快(更快)
  • 程序低耦合便于对未来程序架构进行优化(更友好)