Tree Shaking
用于移除上下文中未引用的代码(dead code),依赖于 ESM 的 静态结构属性。那,什么是静态属性结构呢,有这样一段解释:
Current JavaScript module formats have a dynamic structure: What is imported and exported can change at runtime. One reason why ES6 introduced its own module format is to enable a static structure, which has several benefits. But before we go into those, let’s examine what the structure being static means.
It means that you can determine imports and exports at compile time (statically) – you only need to look at the source code, you don’t have to execute it. ES6 enforces this syntactically: You can only import and export at the top level (never nested inside a conditional statement). And import and export statements have no dynamic parts (no variables etc. are allowed).
基于静态属性结构,我们可以在编译时找出依赖,因此给 Webpack 的打包工作,带来以下好处:
- 更少的文件意味着更少的请求;
- 压缩效率提高,压缩单个打包文件优于压缩多个打包文件;
- 打包时删去没用到的代码,节省空间;
第#1条随着 http2 的出现变得不太重要了,第二条与压缩算法有关,而第#3条只有依赖 静态模块 才能做到,就是 Tree Shaking;
在使用 Webpack 时,我们尝试一下引入模块但是不使用,可以发现打包后,这部分代码被引入了但是标记上了注释
unused。
为什么这样呢,为什么不能直接在打包时删除呢?
因为代码是可能有 副作用(side-effect) 的,有副作用的代码即在导入时会执行一些代码,而不是仅仅暴露自身;
解决办法是,我们在 package.json 中,指明哪些模块是有 side-effect 的(sideEffects 属性),这样我们就找到了 dead code(引入了却没有使用 且 没有副作用的代码);
最后,我们需要 webpack 帮我们在打包过程中删除他们,即使用 uglifyjs 插件,当我们在配置中 将 mode 改为 production 时,会自动启用;