sideEffects 副作用

package.json 中配置 "sideEffects": false 是一个非常重要的 工程化优化配置,它直接影响 Webpack、Vite、Rollup 等现代前端构建工具的 Tree Shaking(摇树优化)行为。

我们来深入解析这里的“副作用”到底是什么意思。


一、“副作用”(sideEffects)在这里是什么意思?

在 JavaScript 模块系统中,“副作用”指的是模块在被导入时,除了导出值之外,还会执行一些其他操作,这些操作可能会影响程序的其他部分。

有副作用的例子:

// utils.js
console.log("This module has side effects!"); // ← 这是一段副作用代码

export const add = (a, b) => a + b;
// polyfill.js
// 这个模块没有导出任何东西,但它修改了全局对象
Array.prototype.myCustomMethod = function () {
  /* ... */
}; // ← 副作用:修改全局原型
// theme.css
body { background: red; } // ← 副作用:执行时会应用样式

这些代码虽然可能没有 export,但它们在被引入时会执行某些逻辑,比如:

  • 修改全局对象
  • 注册事件监听
  • 执行 console.log
  • 注入 CSS 样式
  • 注册服务 worker 等

这些都被称为 “副作用”


二、"sideEffects": false 的作用

当你在 package.json 中写:

{
  "sideEffects": false
}

你是在告诉构建工具(如 Webpack):

“这个包里的所有模块都是 纯的(pure),没有任何副作用。如果某个模块没有被使用到,即使它被导入了,也可以安全地移除。”

效果:启用更激进的 Tree Shaking

例如,你只用了库中的一个函数:

import { debounce } from "lodash-es";

由于 lodash-espackage.json 声明了 "sideEffects": false,构建工具就知道:其他未被引用的模块(如 throttle, cloneDeep 等)可以安全删除,最终打包体积更小。


三、"sideEffects": false vs "sideEffects": []

配置 含义
"sideEffects": false 整个包都没有副作用,可以对所有未使用的模块进行 Tree Shaking。
"sideEffects": ["./dist/style.css", "./polyfill.js"] 大部分模块无副作用,但列出的这些文件有副作用,不能被摇掉。

示例:

{
  "sideEffects": [
    "*.css", // 所有 CSS 文件都有副作用(会注入样式)
    "./polyfills.js" // 这个文件会修改全局环境
  ]
}

这样,构建工具就会保留这些文件,即使它们没有被显式“使用”。


四、实际工程意义

优点:

  1. 减小打包体积:未使用的代码会被完全移除。
  2. 提升加载性能:更小的 JS 文件意味着更快的下载和解析。
  3. 现代框架标配:React、Vue、Lodash、Moment.js 等主流库都合理配置了 sideEffects

注意事项:

  • 如果你写了一个库,并且包含 CSS、polyfill 或全局初始化逻辑,不能简单设置 sideEffects: false,否则这些代码可能被误删。
  • 应用项目(App)通常不需要关心这个,但库(Library)开发者必须正确配置

五、常见误区

误解 正解
“sideEffects 是指函数有副作用” 不是。这里指的是 模块级别 的副作用,不是函数式编程中的“纯函数”。
“设置 false 就能自动优化” 不一定。你还得用 ES Module 语法(import/export),并且代码要支持静态分析。
“所有项目都要加” 只有当你发布一个 npm 包时才需要配置。应用项目可不写。

总结

关键点 说明
sideEffects 指模块在导入时是否执行了除导出之外的操作(如改全局、打日志、加样式)。
"sideEffects": false 告诉构建工具:“这个包是纯的,可以放心删除未使用的模块”。
核心价值 支持更高效的 Tree Shaking,减小最终打包体积。
适用场景 主要用于 npm 库的发布,让使用者获得更小的 bundle。

💡 简单记忆:
“没有副作用” = “可以安全删除没用的代码”
“有副作用” = “哪怕没引用,也不能删”(比如 CSS 文件)