Webpack之Tree Shaking与Scope Hoisting
一、Tree Shaking
Tree-shaking翻译过来就是摇树,作用就是用来【摇掉】代码中为引用的部分==未引用代码(dead-code)。webpack生产环境优化中就有这么一个功能,它可以自动检测出我们代码中那些未引用的代码,然后移除掉它们。
示例:
// components.js
export const Button = () => {
return document.createElement('button')
console.log('dead-code'); // 未引用代码
}
export const Link = () => {
return document.createElement('a')
}
export const Heading = () => {
return document.createElement('h' + level)
}
// main.js
import { Button } from "./components.js"
document.body.appendChild(Button())
我们在components.js中导出了三个成员,在main.ja中只导入了一个Button,如此其他两个成员都是未引用代码。
执行打包,查看bundle.js
// bundle.js
(()=>{"use strict";document.body.appendChild(document.createElement("button"))})();
可见,bundle.js中清除了这些未引用代码。
二、webpack中使用Tree-shanking
需要注意的是,Tree-shaking并不是webpack中的某一个配置选项,而是一组功能搭配使用后的优化效果,这组功能会在生产环境下自动启用。
我们先将打包模式改为"none",执行打包。
可以看到Link和Heading虽然外部没有引入,但还是被导出了,这些导出是没有意义的,接下来我们借助一些优化功能将其去掉。
// webpack.config.js
module.exports = {
mode:"none",
entry:"./src/main.js",
output:{
filename:"bundle.js"
},
// optimization是用来集中配置一些webpack优化功能的
optimization:{
usedExports:true // 表示输出结果中只导出那些在外部使用了的成员
}
}
重新打包
components中就不再导出Link和Heading这两个成员了,而VScode也就这两个函数的字体变淡了,表示它们未被使用。
我们再向optimization中添加一个 minimize: true
,开启压缩代码功能,压缩代码的同时会将那些未引用代码移除。
执行打包,效果如下:
bundle.js中已经没有了Link和Heading相关代码了。
至此就实现了Tree-shaking效果。
如果将我们的代码看作一颗大树的话,可以理解成:usedExports负责标记【枯树叶】,也就是未引用代码,minimize负责【摇掉】它们。
三、Scope Hoisting
除了usedExports属性,我们还可以用一个concatenateModules属性继续优化我们的输出。
普通的打包结果是将我们的每一个模块单独放在一个函数当中,如果我们模块很多,也就意味着我们在输出结果中会有很多这样的模块函数。
我们可以通过concatenateModules属性解决这个问题。
optimization:{
usedExports:true, // 表示输出结果中只导出那些在外部使用了的成员
concatenateModules: true
}
以下为配置concatenateModules属性的前后打包对比:
concatenateModules的作用就是尽可能的将所有模块合并输出到一个函数,这样既提升了运行效率,又减少了代码体积。这个特性又被称为Scope Hoisting,也就是作用域提升,它是webpack3当中添加的一个特性,再配合minimize,代码的体积又会减小很多。