В процессе сборки модулей ключевую роль играет устранение неиспользуемого кода (tree-shaking). Для корректной работы этого механизма сборщик должен понимать, какие модули при импорте выполняют побочные эффекты, а какие являются «чистыми» и могут быть безопасно удалены при отсутствии использования экспортов.
Поле sideEffects в
package.json служит декларацией поведения пакета
относительно побочных эффектов. Оно используется как подсказка для
сборщиков, включая esbuild, позволяя оптимизировать граф зависимостей и
безопасно удалять неиспользуемые части кода.
Модуль считается имеющим побочные эффекты, если при его импорте происходит что-то, выходящее за рамки экспорта значений:
// module.js
window.APP_VERSION = "1.0.0";
export const value = 42;
Даже если value не используется, сам факт импорта
изменяет глобальное окружение.
Противоположный случай:
// pure.js
export function sum(a, b) {
return a + b;
}
Такой модуль может считаться «чистым», если он не выполняет действий при загрузке.
Поле может принимать два основных вида значений:
{
"sideEffects": false
}
Значение false означает, что все файлы пакета не
содержат побочных эффектов. Это самый агрессивный режим
оптимизации.
{
"sideEffects": [
"*.css",
"./src/polyfills.js"
]
}
В этом случае:
esbuild выполняет быстрый анализ модулей и опирается на
sideEffects для принятия решений о включении или исключении
файлов.
Основной принцип:
При наличии:
{
"sideEffects": false
}
esbuild считает:
Пример:
import "lib/register";
import { add } from "lib/math";
Если register не влияет на итоговый результат сборки,
esbuild может удалить этот импорт.
Массив позволяет точечно контролировать поведение:
{
"sideEffects": [
"**/*.css",
"src/init.js"
]
}
Поведение:
Tree-shaking в esbuild строится на нескольких уровнях:
sideEffectsЕсли одновременно выполняются условия:
то модуль удаляется из итогового бандла.
esbuild более эффективно оптимизирует ESM-модули, поскольку их структура статически анализируема.
export const a = 1;
export const b = 2;
Легко удаляются неиспользуемые экспорты.
module.exports = {
a: 1,
b: 2
};
Tree-shaking ограничен, но sideEffects всё равно влияет
на включение самого файла.
CSS часто рассматривается как побочный эффект, поскольку его импорт изменяет глобальное состояние страницы.
{
"sideEffects": [
"*.css"
]
}
import "./styles.css";
Даже если CSS не связан с JS-логикой, его удаление недопустимо.
{
"sideEffects": false
}
при наличии:
import "./polyfill";
Если polyfill изменяет глобальные объекты, его удаление приведёт к нестабильному поведению приложения.
{
"sideEffects": [
"src/**"
]
}
В этом случае оптимизация почти полностью отключается, так как каждый файл считается потенциально опасным.
Если поле не указано:
Важно различать:
// logger.js
console.log("module loaded");
export function log() {}
Даже если log не используется, сообщение может быть
выведено при импорте, что делает модуль side-effectful.
Корректная настройка sideEffects позволяет esbuild:
При этом важна точность декларации, так как сборщик не анализирует динамическое поведение глубже статических признаков.
Плагины esbuild, работающие с импортами CSS, SVG или других ресурсов,
также учитывают sideEffects:
Многие npm-пакеты используют:
{
"sideEffects": false
}
как сигнал для современных сборщиков:
Однако поведение может отличаться в деталях, особенно при смешанных ESM/CJS пакетах.
Упрощённая модель:
sideEffectsУменьшение количества учитываемых модулей приводит к:
Особенно заметно в монорепозиториях и UI-фреймворках с большим количеством утилитарных модулей.