tree-shaking实战


转自  https://www.jianshu.com/p/7994b1fc6dfe

tree-shaking是一个在前端领域比较熟知的东西了。在没有深入了解前,一直以为他在项目中发挥了很大的作用。但是在看了许多文章说tree-shaking并没有什么卵用后,想自己深入了解一下,所以搜了许多博文,自己也在项目中试验了一下。基本了解了大致的流程。所以这篇博文主要是记录一下学习的成果。

tree-shaking是干啥的:


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


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

在看过这些篇博文后,我本人对于tree-shaking有了一个基本的认识,那就是

babel首先处理js文件,真正进行tree-shaking识别和记录的是webpack本身。删除多于代码是在uglify中执行的

注:webpack在认定某块代码无用后,会再处理过程中写下一段注释。uglifyjs会根据这点注释去进行删除代码。

直接复制这篇博文代码

注释的大体内容(博文很久了,还是在webpack2.0时代,具体内容可能已经变化,但原理应该是不变的。)


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进行兼容性处理。


export { default as F } from './F';
export { default as T } from './T';
export { default as __ } from './__';
export { default as add } from './add';
export { default as addIndex } from './addIndex';
export { default as adjust } from './adjust';
export { default as all } from './all';
export { default as allPass } from './allPass';
export { default as always } from './always';
export { default as and } from './and';
export { default as any } from './any';
export { default as anyPass } from './anyPass';
export { default as ap } from './ap';
export { default as aperture } from './aperture';
export { default as append } from './append';
export { default as apply } from './apply';
export { default as applySpec } from './applySpec';

...

这样的文件结构是无法进行tree-shaking的


import path from 'ramda/src/path'


但是如果每一次引用都是这样去写,开发的效率就无法保证,所以基本上有点追求的技术团队,基本上会再类库的基础上,开发一个babel的插件以支持代码的tree-shaking。

像著名的antd,以及ramda等都开发了相应的插件。

babel-plugin-ramda:此插件会默认将你写的代码转化为tree-shaking的代码


from:

import {path} from 'ramda' 

to

import path from 'ramda/src/path'


而本人也在了解了以上东西后,为本公司的ui组件开发了一个插件:

babel-plugin-b-rc

在看过ramda的代码,以及他的构建过程和对于tree-shaking的支持后,学到了很多。有的时候学习webpack以及如何优化网页的时候,不知道如何下手。我的经验就是找到一个技术点,进行深入。比如我得研究点就是tree-shaking,在一路研究过后,babel,babel-preset, babel-plugin,webpack,webpack-plugin,都有了一定的了解。这几个功能点基本上花费了我将近一个多月的时间。从找材料,到动手完成自己的一个babel插件,收获颇丰。学习babel以及webpack的过程,其本质是学习如何优化网页的过程!!!!



作者:strong9527
链接:https://www.jianshu.com/p/7994b1fc6dfe
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。