简说tree-shaking

       tree-shaking是前端领域一个比较常见的词了,在项目中有什么用呢?这个之前一直没搞明白,通过翻阅众多博文,自己在项目中试验了一下,弄清其大致流程,这里就做了个简单记录。

先看一段代码

// app.js

export function A(a, b) {
    return a + b
}

export function B(a, b) {
    return a + b
}

// index.js

import {A} from '/app.js'

A(1, 2)

// 当index.js引用了app.js的A函数,如果tree-shaking起了作用,B函数是不会被打包进最后的bundle的。

       然鹅,在webpack的官网有一句话: rlies on the structure of ES2015 modules syntax , i.e.import an export,翻译一下就是tree-shaking依赖ES6的模块输入输出语法,如果你的模块引入方式是require等,tree-shaking是不会起作用的。

       在开发打包中,我们常用的是babel, webpack,uglifyJs这三样神器,而tree-shaking就是在第一步起作用的,在webpack对js文件处理的过程中,先是babel-loader去处理js文件,处理过后,webpack进行打包处理,最后由ugligyJs进行代码压缩。babel的配置文件中有一项配置很关键,就是preset:

{
  "presets": [
    ["env", {
      "modules": false  //关键点
    }],
    "stage-2",
    "react"
  ]
}

在这个配置里面env的options中有一个modules: false,这个是指示babel如何去处理import和export的关键,默认处理成require形式,如果加上此option,那么babel就不会把import转变成requier形式,为webpack进行tree-shaking创造了条件。

        综上所述,简单来说tree-shaking就是删除项目中无用的代码,压缩项目体积。

webpack对文件tree-shaking的过程如下:

       在认定某块无用后,会在处理过后写下一段注释,uglifyJs会根据这段注释去删除代码


function(module, exports, __webpack_require__) {
    /* harmony export */ exports["foo"] = foo;
    /* unused harmony export bar */;

    function foo() {
        return 'foo';
    }
    function bar() {
        return 'bar';
    }
}

在tree-shaking学习的过程中,可以对class进行tree-shaking,是比较有意思的,找了一个demo,支持tree-shaking:

1.首先使用loader去处理,实验阶段的代码,编译成es代码,这样webpack内部的编译器才能正确识别代码。


module: {
rules: [
  {
    test: /\.js$/,
    use: [
      {
        loader: 'babel-loader',
        options: {
          presets: ['babel-preset-stage-2', 'babel-preset-react']
        }
      },
      'eslint-loader'
    ],
    exclude: /node_modules/
  }
]
}

2.通过webpack打包,并对代码进行tree-shaking,在打包完成的bundle后,和输出的文件之前,对最后的bundle进行兼容性处理。

plugins: [
    new UglifyJSPlugin(),  //  uglify要在babelPugin的前面
    new BabelPlugin({  //在这个插件内部进行最后bundle的兼容性处理
      test: /\.js$/,
      babelOptions: {
        presets: [env]
      }
    }),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production')
    }),
    new HtmlWebpackPlugin({
      template: 'index.html'
    }),
  ]

最后总结步骤:

1.先编译实验性质代码为标准代码,会涉及到babel-preset-stage-x插件

2.webpack打包代码并进行tree-shaking识别

3.uglifyjs进行代码压缩,并根据webpack标识删除多余代码

4.对最后的代码进行兼容性处理涉及到babel-preset-env插件

第三方类库的tree-shaking

在研究了许多第三方类库后,基本得出的结论是,tree-shaking是不能对大部分的第三方类库进行的。

猜你喜欢

转载自blog.csdn.net/Qianliwind/article/details/108689919