️ package.json 中的 sideEffects

在一个库的 package.json 看到了 sideEffects 这个字段,好奇它的作用,查资料可得:

webpack v4 开始新增了一个 sideEffects 特性,通过给 package.json 加入 sideEffects声明该 包/模块 是否包含 sideEffects(副作用),从而可以为 tree-shaking 提供更大的优化空间。

主要意思就是,加了这个字段,打包工具可以更好地为 tree-shaking 工作。让我们来看看它是如何工作的。sideEffects 对 webpack 构建过程有着很大影响, 对 npm 模块尤为重要. 使用中要特别注意声明的正确性。

以下转载于:https://libin1991.github.io/,样例代码:https://github.com/JexLau/demo/side-effects

🌰 小例子

项目存在 utils/a.js , utils/b.js, utils/index.js 三个文件,其中 b 模块包含一条打印语句, 是具有副作用的。

// utils/a.js
export function a() {
   console.log('aaaaaaaaaaaaa');
}

// utils/b.js
console.log('======== b.js ==========');
export function b() {
   console.log('bbbbbbbbbbbbbb');
}

// utils/index.js
export * from './a';
export * from './b';

添加主入口 app.js, 只引用 a 模块, 期望未使用的 b 模块被 tree-shaking 掉

// app.js
import { a } from './utils';
a();

看一下打包后的结果, 注意要在 production 模式下打包。结果如下所示:打包结果中, 不包含 b 模块, 但是 b.js 中的副作用代码被保留了, 这是合乎情理的。

// output
function a() {
  console.log("aaaaaaaaaaaaa");
}
console.log("======== b.js ==========");
a();
🪬 sideEFfects 作用

下面修改下 b.js 的内容,在Array 原型链上定义了一个新方法 sum, 这是具有副作用的. 然后在 b 模块中调用了该方法, 但是作为 b 模块的维护者, 我又希望 sum 是”纯粹”的, 只被我使用, 外部并不依赖它的实现:

// utils/b.js
Object.defineProperty(Array.prototype, 'sum', {
   value: function() {
       return this.reduce((sum, num) =sum += num, 0);
   }
})
export function b() {
   console.log([1, 2, 3, 4].sum());
}

没添加sideEffects之前:

!function(){
    "use strict";
    Object.defineProperty(Array.prototype,"sum",{value:function(){return this.reduce(((a,e)=>a+e),0)}}),
    console.log("aaaaaaaaaaaaa")
}();

添加字段 "sideEffects": false, 该字段表明整个工程是”无副作用”的。重新调用编译, 期待在 b 模块没被使用的情况下, b 中定义的 sum 方法也被 tree-shaking 掉, 结果如下:

!function(){"use strict";console.log("aaaaaaaaaaaaa")}();

如期望那样, 整个 b 模块都被 tree-shaking 掉了, 包括包含副作用的代码。

所以, sideEffects 可以优化打包体积, 并且一定程度上可以减少 webpack 对源码分析过程, 加快打包速度

sideEffects 配置

sideEffects 除了能设置 boolean 值, 还可以设置为数组, 传递需要保留副作用的代码文件(例如: “./src/polyfill.js”) 或者传递模糊匹配符(例如: “src/*/.css”)

sideEffects 注意事项

实际项目中, 通常并不能简单的设置为 "sideEffects": false, 有些副作用是需要保留的, 比如引入样式文件。

webpack 会认为所有 import 'xxx' 语句是仅引入而未使用, 如果你错误的将其声明成了”无副作用”, 它们就会被 tree-shaking 掉, 并且由于 tree-shaking 仅在 production 模式生效, 本地开发时可能一切仍是正常的, 生产环境并不能及时发现问题。

下面这些都是”仅引入而未使用”的例子:

import './normalize.css';  
import './polyfill';  
import './App.less';

这些有副作用的文件, 我们要正确声明, 修改 sideEffects 值:

// package.json  
"sideEffects": [  
 "./src/**/*.css"  
]

sideEffects 局限性

sideEffects 配置是以文件为维度的, 只要你配置了文件具备副作用, 即便你只用了该文件中没有副作用的那部分功能, 仍然会将副作用保留。

比如将 b.js 修改为

Object.defineProperty(Array.prototype, 'sum', {
   value: function() {
       return this.reduce((sum, num) =sum += num, 0);
   }
})
export function b() {
   console.log([1, 2, 3, 4].sum());
}
export function c() {
   console.log('ccccccccccccccccccc');
}

在 app.js 中仅引入 c 方法, b 方法会被 tree-shaking, 但 sum 方法不会。

从这个角度来看,sideEffects 是通知 webpack 该模块是可以安全的 tree-shaking 的, 无需关心其副作用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值