Tree Shaking

顾名思义,摇树,如果把整个项目想象成一棵树,那么实际用到的源码就相当于树上的绿色的活的树叶,而灰色的则表示无用的代码,是秋天树上枯萎的树叶。为了除去死去的树叶,你必须摇动这棵树,使它们落下(清除无用的代码)

举例说明:
  1. 假如有src/math.js,该文件导出(export)了两个方法
export const add = (x, y) => {
    console.log(x+y)
}

export const minus = (x, y) => {
    console.log(x-y)
}
  1. 然后我们在src/index.js里引入其中一个方法
import { add } from './math.js'

add(1, 2);
  1. 然后我们运行打包命令 npx webpack,控制台输出了3
    Tree Shaking_第1张图片
    image.png
  2. 观察我们的打包文件main.js,发现webpack帮我把src/math.js文件里的两个方法都打包进来了,但是我们明明只引用了一个方法,这是很不合适的,如果项目非常大,那打包出的文件体积将会非常大。这个时候,我们就需要用Tree Shaking来帮我们摇晃掉我们没有引入的模块,只打包我们引用的模块
    Tree Shaking_第2张图片
    image.png

注意 : Tree Shaking 它依赖于 ES2015 模块系统中的静态结构特性,例如 importexport,也就是说只支持ES Module 这种静态引入的方式,不支持 CommonJs这种动态引入的方式(const add = require('./math.js'))

  1. 我们刚才打包的时候,webpack.config.js里的mode是development的模式,这种开发模式默认是不带Tree Shaking这个功能的。那我们怎么在开发环境中使用Tree Shaking呢?
    Tree Shaking_第3张图片
    image.png
  2. 然后我们在package.json里加一个配置
    Tree Shaking_第4张图片
    image.png

通过 package.json"sideEffects"属性作为标记,向compiler 提供提示,表明项目中的哪些文件是 "pure(纯的 ES2015 模块)",由此可以安全地删除文件中未使用的部分。
如果所有代码都不包含副作用,我们就可以简单地将该属性标记为 false,来告知 webpack,它可以安全地删除未用到的 export 导出。
「副作用」的定义是,在导入时会执行特殊行为的代码,而不是仅仅暴露一个 export 或多个 export。举例说明,例如 polyfill,它影响全局作用域,并且通常不提供 export。
如果你的代码确实有一些副作用,那么可以改为提供一个数组:
注意,任何导入的文件都会受到 tree shaking 的影响。这意味着,如果在项目中使用类似 css-loader 并导入 CSS 文件,则需要将其添加到 side effect 列表中,以免在生产模式中无意中将它删除:

比如,我们之前引入的import @babel/poly-ill, 它实际上并没有导出任何的内容,这个模块实际上是在window对象上绑定了一些全局变量 ,比如 window.Promise等 ,但是假如我们用了tree shaking,有可能tree shaking就发现这个模块没有导出任何的内容,有可能在打包的时候,就直接把@babel/poly-ill 给忽略掉了,但实际上,我们是需要这个模块的。这个时候打包就会出错了。
我们可以把这些导入的,有副作用的文件,放到一个数组里

Tree Shaking_第5张图片
image.png

这样在打包的时候, tree shaking就不会对这些模块起作用,至于其他的导入模块,该怎么就怎么样
因为我们这个例子里没有需要特殊处理的模块,所以我们的 sideEffects还是设置为 false

  1. 然后我们再运行打包命令,打开生成的main.js文件,可以看到tree shaking已经生效了
    Tree Shaking_第6张图片
    image.png

注意,在开发环境下做打包的时候,即使我们用了tree shaking webpack也不会直接把没有用到的模块从打包生成的文件里直接剔除,它只会在代码里提示了我们一下哪些被使用了。
这是因为,我们在开发环境下生成的代码,需要做一些调试,如果tree shaking把一些代码删除掉的话,那么在做调试的时候,代码对应的行数,sourcemap对应的行数就可能出现错误,所以开发环境下tree shaking还会保留这些没用到的代码
如果我们的代码要打包上线,我们把mode改为production的时候,tree shaking就完全生效了

当然,如果把mode改为production的时候,devtool也要做相应的改变,我们之前说过,线下环境最好是改为:

Tree Shaking_第7张图片
image.png

而且production模式下,tree shaking一些配置已经自动写好了,我们甚至不需要写下边这个配置了

Tree Shaking_第8张图片
image.png

但是下边这个配置,还是需要写的
Tree Shaking_第9张图片
image.png

  1. 当我们做好了production环境下的配置后,我们再进行一次打包,可以发现生成的压缩文件main.js里,add方法可以找到,minus方法就没有打包进来了


    Tree Shaking_第10张图片
    image.png

    Tree Shaking_第11张图片
    image.png
一句话,tree shaking指的 就是当我引入一个模块的时候,我不引入这个模块所有的代码,我只引入需要的代码

你可能感兴趣的:(Tree Shaking)