Поле sideEffects в package.json
используется сборщиком модулей (в первую очередь Webpack) для анализа
побочных эффектов модулей и оптимизации tree shaking. Его основная
задача — помочь определить, какие файлы можно безопасно удалить при
сборке, если их экспортированные значения не используются.
В основе механизма лежит предположение: если модуль не содержит побочных эффектов, то его импорт можно считать «чистым» и потенциально удалить при отсутствии использования экспортов. Однако JavaScript по своей природе допускает выполнение кода при импорте, поэтому без явного указания невозможно гарантировать безопасность удаления.
Под побочными эффектами понимаются любые операции, которые происходят при загрузке модуля и не связаны напрямую с его экспортами:
Пример:
// logger.js
console.log('logger initialized');
export function log(msg) {
console.log(msg);
}
Даже если log не используется, строка
console.log('logger initialized') выполнится при импорте.
Это и есть побочный эффект.
При включённом tree shaking Webpack анализирует ESM-экспорты и удаляет неиспользуемые части кода. Однако без дополнительной информации он вынужден считать, что любой импорт может иметь побочные эффекты.
import { log } from './logger';
Если модуль не используется напрямую, но импортирован, Webpack не сможет безопасно удалить его, если не уверен в отсутствии побочных эффектов.
Поле sideEffects объявляется в package.json
и сообщает сборщику, содержит ли пакет модули с побочными эффектами.
{
"sideEffects": false
}
Значение false означает:
Это максимально агрессивный режим оптимизации.
{
"sideEffects": [
"*.css",
"*.scss"
]
}
В этом случае:
Типичный пример — стили:
import './styles.css';
CSS импорт часто не имеет JS-экспортов, но его удаление приведёт к потере стилей. Поэтому он явно помечается как побочный эффект.
Tree shaking работает только в условиях статического анализа ESM:
import / export должны быть
статическимиWebpack использует sideEffects как дополнительный
сигнал:
false → можно удалять неиспользуемые импорты даже без
анализа содержимогоЧастая проблема связана с импортом немодульных ресурсов:
import './reset.css';
import './theme.css';
Если не указать sideEffects, Webpack может ошибочно
удалить такие импорты при оптимизациях.
Правильная конфигурация:
{
"sideEffects": [
"*.css",
"*.scss",
"*.sass"
]
}
Это позволяет:
Для библиотек sideEffects критически важен, поскольку
они распространяются как зависимости.
{
"name": "math-utils",
"sideEffects": false
}
Такая библиотека:
Пример кода:
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}
Если используется только add, функция
multiply исключается из бандла.
{
"sideEffects": [
"./polyfills.js"
]
}
// polyfills.js
import 'core-js/stable';
import 'regenerator-runtime/runtime';
Такой файл должен выполняться всегда, даже если его экспорты не используются.
Webpack имеет собственную настройку:
module.exports = {
optimization: {
sideEffects: true
}
};
Она включает анализ поля sideEffects. В production
режиме обычно включено по умолчанию.
Если отключить:
optimization: {
sideEffects: false
}
то:
sideEffectsНеверная конфигурация может привести к серьёзным проблемам.
{
"sideEffects": false
}
Если пакет фактически содержит:
import './global.css';
window.APP_VERSION = '1.0.0';
то при tree shaking:
Если поле не задано:
sideEffects наиболее эффективно работает с ES
Modules:
В CommonJS:
const mod = require('./mod');
tree shaking ограничен, поэтому sideEffects почти не
даёт эффекта.
При анализе модуля происходит цепочка:
importsideEffectsЕсли одновременно:
то модуль удаляется полностью.
import('./module.js');
Для динамических импортов:
sideEffects не влияет на загрузку самого чанкаСовременные npm-пакеты стремятся к:
Типичная структура:
src/
index.js
pure/
side-effects/
dist/
И соответствующая конфигурация:
{
"sideEffects": [
"./dist/side-effects/**"
]
}
falseTree shaking и sideEffects работают до этапа
минификации. После удаления неиспользуемых модулей:
sideEffects можно рассматривать как контракт: