Поле sideEffects в package.json
используется как декларативный сигнал для сборщиков о том, содержит ли
пакет побочные эффекты при импорте модулей и можно ли безопасно удалять
неиспользуемые части кода при tree-shaking. В экосистеме модульной
сборки это поле стало ключевым элементом оптимизации, особенно в связке
с ES-модулями и статическим анализом графа зависимостей.
Побочным эффектом считается любое выполнение кода при импорте модуля, которое влияет на внешнее состояние приложения вне экспортируемых значений. Это может включать:
window,
globalThis)Пример модуля с побочным эффектом:
// polyfill.js
import './setupGlobals.js';
window.myPolyfillEnabled = true;
Даже если модуль не экспортирует ничего, его импорт изменяет состояние окружения, поэтому удаление такого импорта может сломать приложение.
Поле sideEffects задаёт сборщику правило: можно ли
считать файлы пакета «чистыми» (pure) с точки зрения удаления
неиспользуемого кода.
Форматы значения:
{
"name": "my-library",
"sideEffects": false
}
Это означает:
{
"name": "my-library",
"sideEffects": true
}
Это означает:
{
"name": "my-library",
"sideEffects": [
"*.css",
"./src/polyfills.js"
]
}
Здесь:
polyfills.js сохраняетсяTree-shaking основан на анализе ES-модулей, где импорт и экспорт статически определены. Однако одного анализа недостаточно: сборщик должен понимать, можно ли безопасно удалить импортируемый модуль, если его экспорт не используется.
При sideEffects: false сборщик делает предположение:
Пример:
import { helper } from 'utils';
Если helper не используется, весь импорт может быть
удалён.
При включённых побочных эффектах:
Rollup выполняет tree-shaking на основе статического анализа графа
модулей ES6. В отличие от некоторых других сборщиков, Rollup не
полагается исключительно на sideEffects, но может учитывать
его через плагины резолвинга зависимостей.
Основные особенности:
sideEffects используется как дополнительная подсказка
при работе с npm-пакетами@rollup/plugin-node-resolveПри сборке зависимостей из node_modules поле
sideEffects может повлиять на решение о том, можно ли
безопасно выкинуть неиспользуемые импорты внутри пакета.
Рассмотрим библиотеку:
{
"name": "ui-kit",
"sideEffects": false,
"module": "dist/index.js"
}
И файл:
// button.js
export function Button() {
return document.createElement('button');
}
// index.js
export { Button } from './button.js';
export { Modal } from './modal.js';
Если пользователь импортирует только Button:
import { Button } from 'ui-kit';
Rollup может построить граф:
При наличии sideEffects: false модуль
modal.js может быть полностью исключён из бандла.
Частичный режим применяется в реальных библиотеках чаще всего, так как CSS и регистрационные модули почти всегда имеют побочные эффекты:
{
"sideEffects": [
"*.css",
"*.scss",
"./src/polyfills.js",
"./src/registerServiceWorker.js"
]
}
Это позволяет:
CSS-импорты через JS являются типичным примером побочных эффектов:
import './styles.css';
Удаление такого импорта приведёт к отсутствию стилей в приложении, поэтому:
sideEffects: false используется исключение
*.cssНеправильная настройка приводит к критическим проблемам:
{
"sideEffects": false
}
Если в пакете есть:
import './init.js';
где init.js регистрирует глобальные обработчики, сборщик
может удалить этот импорт, что приведёт к неработоспособности
функционала.
{
"sideEffects": true
}
Результат:
sideEffects наиболее эффективно работает с
ES-модулями:
При наличии CJS-зависимостей sideEffects становится
дополнительным фактором решения о сохранении модулей.
При анализе модуля сборщик учитывает:
sideEffectsПри sideEffects: false вероятность удаления модуля
значительно выше, при условии отсутствия прямого использования
экспортов.
Правильная настройка sideEffects напрямую влияет на:
Особенно заметно это в больших UI-библиотеках и design system-пакетах, где десятки компонентов могут быть импортированы, но используется только часть.
Базовая структура package.json в библиотеке:
{
"name": "component-library",
"version": "1.0.0",
"module": "dist/index.js",
"sideEffects": [
"*.css"
]
}
Такой подход:
sideEffects выступает метаданными уровня пакета, которые
дополняют статический анализ модулей. В связке с Rollup он усиливает
точность tree-shaking при работе с внешними зависимостями, не заменяя
анализ, а уточняя границы безопасного удаления кода.