前言
webpack4新增了一个sideEffects新特性,它允许我们通过配置的方式,去标识我们的代码是否有副作用,从而为Tree-shaking提供更大的压缩空间。
这里的副作用指的是模块执行时除了导出成员之外所做的事情。
sideEffects一般用于npm包标记是否有副作用。
一、sideEffects的使用
文件结构:
测试文件代码如下:
// components/button.js
export const Button = () => {
return document.createElement('button')
console.log('dead-code'); // 未引用代码
}
// components/heading.js
export const Heading = () => {
return document.createElement('h' + level)
}
// components/link.js
export const Link = () => {
return document.createElement('a')
}
// components/index.js
export { default as Button } from './button'
export { default as Link } from './link'
export { default as Heading } from './heading'
// index.js
import { Button } from "./components"
document.body.appendChild(Button())
打包,查看效果
未引用代码也被打包了,sideEffects就可以用来解决此类问题。
webpack.config.js新增sideEffects配置
module.exports = {
mode:"none",
entry:"./src/index.js",
output:{
filename:"bundle.js"
},
optimization:{
sideEffects: true
}
}
开启了sideEffects配置后,webpack在打包时就会先检查当前代码所属的package.json中有没有sideEffects的标识,以此来判断这个模块是不是又副作用。如果这个模块没有副作用,这些没被用到的模块就不会被打包。(这个特性在production模式下会自动开启)
在package.json中配置以下"sideEffects":false
此时再去执行打包,bundle.js中就会清除未引用代码了。
二、sideEffects注意事项
使用sideEffects的前提就是确定你的代码真的没有副作用,否则的话,在webpack打包时,就会误删掉那些有副作用的代码。
例如src目录下有一个extends.js文件
// extends.js
Number.prototype.pad = function(size){
let result = this + ""
while(result.length < size){
result = "0" + result
}
return result;
}
在index.js中执行这个模块的内容,为Number原型对象上添加一个pad方法。再执行一个公共css代码模块。
// index.js
import { Button } from "./components"
import "./extends"
import "./global.css"
console.log((8).pad(3));
document.body.appendChild(Button())
打包效果如下:
extends.js模块和global.css模块都没被打包。因为它们都算是副作用模块,而我们在package.json中声明了没有副作用,所以它们就被移除了。
解决办法就是在package.json中关闭副作用,或者标识以下当前文件中有哪些文件是有副作用的。
"sideEffects": [
"./src/extends.js",
"*.css"
]
此时打包就不会移除标识了的副作用模块了。