webpack学习--tree-shaking剔除无用代码

tree-shaking,了解一下?
webpack学习--tree-shaking剔除无用代码_第1张图片

1. 例子

在webpack,在pro模式下,UglifyJSPlugin插件可以为我们适当的压缩代码。

具体是怎么压缩的呢?

配置UglifyJSPlugin

const path = require('path');
+ const UglifyJSPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
- }
+ },
+ plugins: [
+   new UglifyJSPlugin()
+ ]
};

它会利用ES6模块的静态特性:

  1. 只能作为模块顶层的语句出现,不能出现在 function 里面或是 if 里面。(ECMA-262 15.2)
  2. import 的模块名只能是字符串常量。(ECMA-262 15.2.2)
  3. 不管 import 的语句出现的位置在哪里,在模块初始化的时候所有的 import 都必须已经导入完成。换句话说,ES6 imports are hoisted。(ECMA-262 15.2.1.16.4 - 8.a)
  4. import binding 是 immutable 的,类似 const。比如说你不能 import { a } from ‘./a’ 然后给 a 赋值个其他什么东西。(ECMA-262 15.2.1.16.4 - 12.c.3)

—–引用自尤雨溪

来分析js文件的import和export,把未引用代码(dead code)剔除掉。

这里有两个js文件。

a.js

export {
foo,
bar
};
function foo() {
    return 'foo';
}
funtion bar() {
    return 'bar';
}

main.js

import { foo } from 'a.js';

console.log(foo());

之前a.js里面导出了foo和bar两个函数,因为bar从来没有被引用过,uglify plugin认为它是无用代码,将它删掉。

webpack 使用UglifyJSPlugin处理之后的代码:

// 代表之前的a.js
function (t, n, r) {
        function e() {
            return "foo"
        }

        n.foo = e
    }

这个变化叫做tree-shaking

2. tree-shaking由来

tree-shaking来自于rollup.js,原理相同,就是通过分析静态的ES模块,来剔除未使用代码的。

来看一下如果用rollup来压缩:

(function () {
    'use strict';

    function foo() {
        return 'foo';
    }

    let elem = document.getElementById('output');
    elem.innerHTML = `Output: ${foo()}`;

}());

—–引用自顾轶灵

用rollup压缩更优秀一点,直接把模块里面的函数合并到引用文件里。webpack的压缩还保留有无用的嵌套。

3. 总结

如何评价这个东西呢?

还是有一部分用处的。不过只能解决ES模块相关的导入导出暴露出的无用代码优化问题,实际上,js还有更多无用代码,没有暴露在模块出口入口。这就需要compiler来优化。

google的closure compiler,了解一下?

webpack学习--tree-shaking剔除无用代码_第2张图片

4. 参考:

https://medium.com/@Rich_Harris/tree-shaking-versus-dead-code-elimination-d3765df85c80
https://www.zhihu.com/question/41922432

你可能感兴趣的:(webpack)