不能通过配置打包工具“强制剔除”包含原型方法副作用的代码片段,因为向原型添加方法属于运行时全局副作用,Tree Shaking 无法静态分析,且删掉会导致调用失败;正确做法是显式声明 sideEffects、隔离 polyfill、禁用自动优化或人工裁剪。

不能通过配置打包工具“强制剔除”包含原型方法副作用的代码片段。
Tree Shaking 的核心前提是静态可分析性和无副作用声明。而向原型(如 Array.prototype、String.prototype)添加方法,属于典型的运行时全局副作用——它不依赖 import/export 结构,也不在模块顶层直接执行逻辑,而是通过赋值或定义影响全局环境。这类代码:
- 不会被 ES Module 静态分析捕获
- 不受
sideEffects: false控制(因为该字段只标记模块级副作用,不覆盖原型污染) - 即使被 Webpack 或 Rollup 识别为“未引用”,也不会删除——删掉它会导致其他地方调用失败(比如
arr.myMap()),构建工具会保守保留
所以,“强制剔除”不仅不可靠,而且危险。真正可行的做法是:隔离 + 标记 + 禁用自动优化。
明确副作用代码的位置
识别哪些文件执行了原型扩展,例如:
// src/polyfills/array-map.js
if (!Array.prototype.myMap) {
Array.prototype.myMap = function(fn) { /* ... */ };
}这类文件必须显式声明为有副作用,否则 Tree Shaking 可能误删它,引发运行时错误。
✅ 正确做法:在 package.json 中用 sideEffects 列出所有含原型修改的文件
{
"sideEffects": [
"./src/polyfills/array-map.js",
"./src/polyfills/string-pad.js",
"*.css"
]
}避免被误删的配置细节
- 不要将这类文件写成
sideEffects: false或省略sideEffects字段 - 不要用
/*#__PURE__*/注释包裹原型赋值(它只对函数调用有效,对属性赋值无效) - 如果使用
@babel/preset-env,确保shippedProposals: true或手动排除相关 polyfill 插件,防止 Babel 自动生成污染原型的代码
如需裁剪,只能人工移除或条件禁用
- 删除源码中不再使用的原型方法(如确认全项目没调用
String.prototype.capitalize,再删对应文件) - 用环境变量控制加载:
// src/polyfills/index.js if (process.env.ENABLE_POLYFILLS === 'true') { require('./array-map'); }构建时传
--env ENABLE_POLYFILLS=false,配合DefinePlugin替换后,整块代码可被 Terser 消除(前提是没其他引用)
动态原型访问无法被静态分析
像 window[methodName]()、obj.constructor.prototype[method] 这类写法,连 Webpack Deadcode Plugin 都无法检测,更别说自动剔除。它们天然绕过所有基于 import/export 的优化机制。
本质上,原型副作用不属于“死代码”,而是“潜在运行时契约”。打包工具不会、也不该替你决定删还是不删——那是语义层的责任,不是语法层的优化任务。

















