В процессе tree-shaking Rollup строит граф зависимостей и затем выполняет статический анализ того, какие узлы графа могут быть безопасно удалены. При этом важна не только доступность символа, но и характер операций над ним. Одним из наиболее тонких моментов становится различие между вызовом функции, обращением к переменной и чтением свойства объекта.
Чтение свойства в JavaScript формально может быть как «чистой»
операцией (obj.value), так и операцией с побочными
эффектами (get value() { ... }, Proxy,
вычисляемые геттеры). Именно эту неоднозначность и регулирует параметр
treeshake.propertyReadSideEffects.
treeshake.propertyReadSideEffectsПараметр treeshake.propertyReadSideEffects управляет
тем, считает ли Rollup чтение свойства объекта потенциально имеющим
побочные эффекты.
Базовая идея:
true Rollup действует консервативно;false Rollup допускает более агрессивное
удаление кода, считая чтение свойств безопасным.По сути, речь идет о допущении:
можно ли считать
obj.prop“чистой” операцией, которая не влияет на выполнение программы.
true)В стандартной конфигурации:
export default {
treeshake: {
propertyReadSideEffects: true
}
}
Rollup исходит из того, что:
Proxy;Даже если код выглядит безопасным:
const value = obj.something;
Rollup не всегда может гарантировать, что это не изменит состояние программы. Поэтому он склонен сохранять больше кода, особенно если объект:
falseПри отключении:
export default {
treeshake: {
propertyReadSideEffects: false
}
}
Rollup начинает считать, что:
Улучшается степень сжатия и сокращения кода, но увеличивается риск некорректного поведения в случаях, когда:
get;Наиболее проблемная зона — свойства с accessor-логикой:
export const config = {
get token() {
console.log('access');
return computeToken();
}
};
При обращении:
config.token;
происходит выполнение кода.
propertyReadSideEffects: true — Rollup сохраняет
осторожность и может не удалять связанные участки.propertyReadSideEffects: false — Rollup предполагает,
что это чистое чтение, что может привести к удалению кода, влияющего на
поведение.Proxy усиливают неопределенность:
const obj = new Proxy({}, {
get(target, key) {
console.log('access', key);
return 123;
}
});
Любое чтение:
obj.x;
может иметь эффект.
При false Rollup игнорирует этот класс поведения на
уровне анализа, полагаясь на статическую эвристику. При
true сохраняет более осторожную модель.
Особенно важная область —
import * as ns from 'module'.
Namespace-объекты в ESM являются прокси-подобными структурами, где каждое свойство связано с экспортом модуля.
import * as ns from './mod.js';
ns.value;
При включенной осторожной модели Rollup считает такие чтения потенциально значимыми для side effects, так как:
ns.value может инициировать связывание с
модулем;При false Rollup может агрессивнее удалять
неиспользуемые экспорты, считая чтения безопасными.
propertyReadSideEffects влияет на то, как Rollup
помечает узлы графа:
truefalsemoduleSideEffectsЕсли модуль помечен как имеющий побочные эффекты:
{
"sideEffects": true
}
то даже при propertyReadSideEffects: false Rollup может
сохранить модуль целиком.
pure annotationsКомментарии вида:
/*#__PURE__*/ factory()
помогают Rollup понять, что результат вызова можно удалять. Но для
свойств такой уровень аннотаций не применяется напрямую, поэтому роль
propertyReadSideEffects становится критичнее.
export const math = {
add(a, b) {
return a + b;
}
};
Здесь propertyReadSideEffects: false безопасен и
улучшает tree-shaking.
export const config = {
get api() {
return loadApi();
}
};
Здесь отключение может привести к пропуску важного кода.
export { a } from './a.js';
export { b } from './b.js';
При активной агрессивной оптимизации Rollup может удалять
неиспользуемые реэкспорты более эффективно при false.
Установка:
treeshake: {
propertyReadSideEffects: false
}
в больших проектах без контроля качества зависимостей может привести к:
Хотя уменьшение conservative checks ускоряет tree-shaking, основное влияние — не на скорость, а на корректность результата сборки.
Некоторые npm-библиотеки используют:
Для них false может быть небезопасен.
treeshake.propertyReadSideEffects фактически задает
уровень доверия к структуре объектов в кодовой базе.
false) — максимальная
оптимизация;true) — стабильность и
предсказуемость.В крупных приложениях часто важнее предсказуемость, тогда как в библиотечной разработке допустим более агрессивный режим при строгом контроле API.