Механизм sideEffects в экосистеме Webpack используется
для точного указания того, какие модули в пакете можно безопасно удалять
при tree shaking, а какие должны сохраняться независимо от того,
используются ли их экспорты напрямую. Это один из ключевых инструментов
оптимизации, позволяющий существенно уменьшать размер конечного бандла
за счёт исключения неиспользуемого кода.
В контексте модульной системы побочным эффектом считается любое выполнение кода, которое влияет на внешнее состояние приложения вне системы экспорта/импорта. Это может быть:
window,
globalThis)Пример:
// polyfill.js
import 'core-js/es/array';
import 'regenerator-runtime/runtime';
console.log('polyfills loaded');
Даже если этот файл не экспортирует ничего, его выполнение изменяет окружение. Такой модуль нельзя просто удалить как «неиспользуемый».
Tree shaking работает корректно только в случае статического анализа и отсутствия побочных эффектов. Если модуль импортирован, но его экспорт не используется, сборщик может удалить его целиком.
Однако без явного указания возможны ошибки:
import './polyfills.js'; // важно для окружения
Если сборщик посчитает, что файл не используется, он может исключить его, что приведёт к поломке приложения.
Именно для этого существует механизм sideEffects.
Ключ sideEffects указывается в package.json
и сообщает сборщику, какие файлы нельзя безопасно удалять при tree
shaking.
Самый простой вариант:
{
"name": "my-library",
"sideEffects": false
}
Это означает:
Такой вариант возможен только для библиотек, где гарантируется отсутствие побочных эффектов.
Реальный код часто содержит смешанный характер модулей. Тогда используется массив:
{
"sideEffects": [
"*.css",
"./src/polyfills.js",
"./src/globalSetup.js"
]
}
Здесь:
import './button.css';
CSS не экспортирует значений, но его импорт изменяет DOM через style-loader или извлекается в отдельный файл. Поэтому CSS почти всегда считается side effect.
// globalSetup.js
window.appVersion = '1.0.0';
Такой модуль влияет на глобальное окружение и не должен удаляться.
import 'whatwg-fetch';
Добавляет глобальные API, не имея экспортов.
import './patchDate';
Date.prototype.toISO = function () {
return this.toISOString();
};
Любая модификация прототипов является побочным эффектом.
Модуль считается «чистым», если:
Пример:
export function sum(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}
Такой модуль можно безопасно сокращать до используемых экспортов.
Tree shaking в Webpack основан на ESM (ES Modules), так как они обеспечивают статическую структуру импорта:
import { sum } from './math.js';
Если math.js помечен как без побочных эффектов, Webpack
может:
{
"sideEffects": false
}
Если внутри пакета есть:
import './register';
и этот файл изменяет глобальное состояние, он может быть удалён, что приведёт к сбоям.
Если не указать:
"sideEffects": ["*.css"]
CSS может быть исключён из сборки при агрессивной оптимизации.
Практика показывает, что лучше разделять код:
Пример структуры:
src/
core/
math.js
string.js
init/
polyfills.js
setupEnv.js
styles/
main.css
package.json:
{
"sideEffects": [
"./src/init/*.js",
"./src/styles/*.css"
]
}
Корректная настройка sideEffects позволяет:
Webpack может точнее строить dependency graph, исключая ненужные ветви.
Механизм sideEffects работает в связке с:
optimization.usedExportsmode: productionsideEffects отвечает за уровень файла, а
usedExports — за уровень экспортов внутри модуля.
На практике применяют следующие подходы:
"sideEffects": false при полной
уверенностиТак достигается баланс между безопасностью и агрессивной оптимизацией.