Tree Shaking In Practice

引言

随着产品的迭代升级和人员变更,我们的代码往往会逐渐变得不可控,有一点表现的尤为明显,即之前的代码逻辑模块被废弃不用,但是该模块又被引入了进来,对应的模块在编译理论中被称之为 Dead Code。我们可以采用相应的方法把这些 Dead Code 删除掉, 这种解决问题的方法被称为 DCE(Dead Code Elimination)。而 DCE 在前端领域中的实现就是常常被提到的Tree Shaking

Tree Shaking 的作用

Tree Shaking 的相关概念最早是在 Rollup 中引入的,那么我们就以 Rollup(^2.78.0) 来举例:

  1. 新建两个文件main.mjsoutput.mjs,两个文件内容如下:
  • output.mjs

    1
    2
    export const a = 1;
    export const b = 2;
  • main.mjs:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import { a } from './output.mjs';

    console.log(a);
    const c = 3;

    function foo() {
    console.log('aaaa');
    return;
    console.log('bbbb');
    }

    foo();
  1. 执行命令rollup main.mjs --file bundle.js生成bundle.js文件,内容如下:
1
2
3
4
5
6
7
8
9
10
const a = 1;

console.log(a);

function foo() {
console.log('aaaa');
return;
}

foo();

可以看到 output 中的const b = 2;以及 main 中的const c = 3;和 return 之后的console.log('bbbb');在最终打包结果 bundle 中都被移除掉了。对比打包之前和打包之后的结果我们可以总结出 Tree Shaking 主要做了以下几点事情:

  • 消除无用的变量,函数等未被引用的内容
  • 消除代码中不会被执行的逻辑
  • 消除引入的其他模块中不被使用的内容

注意以上列举的几点是 Tree Shaking 通用的作用,但是并不是所有的打包工具都做到了这些,如默认情况下 esbuild 并不能消除掉上述示例代码中 return 之后的部分,但是可以借助工具在压缩阶段去除。

Read more