21 Tree Shaking原理是什么

对tree-shaking的了解

作用:

它表示在打包的时候会去除一些无用的代码

原理

  • ES6的模块引入是静态分析的,所以在编译时能正确判断到底加载了哪些模块
  • 分析程序流,判断哪些变量未被使用、引用,进而删除此代码

特点:

  • 在生产模式下它是默认开启的,但是由于经过babel编译全部模块被封装成IIFE,它存在副作用无法被tree-shaking
  • 可以在package.json中配置sideEffects来指定哪些文件是有副作用的。它有两种值,一个是布尔类型,如果是false则表示所有文件都没有副作用;如果是一个数组的话,数组里的文件路径表示改文件有副作用
  • rollupwebpack中对tree-shaking的层度不同,例如对babel转译后的class,如果babel的转译是宽松模式下的话(也就是loosetrue),webpack依旧会认为它有副作用不会tree-shaking掉,而rollup会。这是因为rollup有程序流分析的功能,可以更好的判断代码是否真正会产生副作用。

原理

  • ES6 Module 引入进行静态分析,故而编译的时候正确判断到底加载了那些模块
  • 静态分析程序流,判断那些模块和变量未被使用或者引用,进而删除对应代码

依赖于import/export

通过导入所有的包后再进行条件获取。如下:

    import foo from "foo";
    import bar from "bar";
    
    if(condition) {
        // foo.xxxx
    } else {
        // bar.xxx
    }

ES6的import语法完美可以使用tree shaking,因为可以在代码不运行的情况下就能分析出不需要的代码

CommonJS的动态特性模块意味着tree shaking不适用 。因为它是不可能确定哪些模块实际运行之前是需要的或者是不需要的。在ES6中,进入了完全静态的导入语法:import。这也意味着下面的导入是不可行的:

    // 不可行,ES6 的import是完全静态的
    if(condition) {
        myDynamicModule = require("foo");
    } else {
        myDynamicModule = require("bar");
    }

补充(现代做法):webpack5 的 Tree Shaking 增强了对「嵌套 / 内部导出」和 CommonJS 的部分摇树支持,并能识别 package.jsonsideEffects: false 跨模块删除未用代码。实践要点:①库作者务必标注 sideEffects;②避免在入口处写有副作用的顶层语句;③import 具名导入而非整包默认导入。基于 Rollup 的工具链(Vite 生产构建)摇树更彻底。

Last Updated:
Contributors: leeguooooo