Аннотация /*#__PURE__*/ представляет собой специальный
комментарий, используемый в JavaScript-коде для обозначения чистых
выражений, не имеющих побочных эффектов. В контексте Rollup и
других современных бандлеров она играет ключевую роль в процессе
tree-shaking, позволяя безопасно удалять неиспользуемый код при
сборке.
Основная идея заключается в том, чтобы явно сообщить статическому анализатору: результат данного выражения не влияет на внешнее состояние программы и может быть отброшен, если он нигде не используется.
Tree-shaking в Rollup основан на анализе ES-модулей и построении графа зависимостей. Каждый экспорт рассматривается как потенциально удаляемый элемент, если он не достигается из точки входа.
Однако статический анализ не всегда способен точно определить наличие побочных эффектов. Особенно это касается вызовов функций, конструкторов и сложных выражений.
В таких случаях используется аннотация:
const value = /*#__PURE__*/ createExpensiveObject();
Она сообщает бандлеру, что:
createExpensiveObject() не имеет побочных
эффектовvalue не
используетсяАннотация всегда размещается непосредственно перед выражением, которое считается «чистым»:
const data = /*#__PURE__*/ factory();
Допустимые формы применения:
const result = /*#__PURE__*/ compute();
const instance = /*#__PURE__*/ new Service();
const value = /*#__PURE__*/ wrap( /*#__PURE__*/ create());
Ключевой момент заключается в том, что комментарий должен находиться строго перед AST-узлом вызова. Любое смещение делает аннотацию неэффективной.
Rollup сам по себе не «исполняет» аннотации, но учитывает их при:
Аннотация влияет на решение: является ли выражение side-effectful или нет.
Если выражение помечено как pure, Rollup может:
ESM является ключевым условием эффективного tree-shaking. Rollup анализирует импорт-экспорт как статический граф:
import { init } from './module.js';
init();
Если init помечен как неиспользуемый или удаляемый, но
внутри него есть вызовы, аннотация /*#__PURE__*/ может
помочь определить безопасность удаления.
В отличие от CommonJS, где динамические require
затрудняют анализ, ES-модули позволяют точно отслеживать
зависимости.
export const store = /*#__PURE__*/ createStore();
Без аннотации Rollup предполагает, что createStore()
может менять глобальное состояние.
export const App = /*#__PURE__*/ createComponent({
name: 'App'
});
Компонент может быть удалён, если не используется, только при уверенности в отсутствии побочных эффектов.
export const config = /*#__PURE__*/ loadConfig();
Если loadConfig() читает файлы или обращается к
окружению, аннотация становится некорректной.
Аннотация /*#__PURE__*/ не выполняет никакой проверки
корректности. Она является исключительно подсказкой для бандлера.
Ключевые ограничения:
package.json поля
sideEffectsВ экосистеме Rollup и связанных инструментов используется два уровня оптимизации:
{
"sideEffects": false
}
Это глобальная декларация о том, что весь пакет не содержит побочных эффектов.
/*#__PURE__*/ fn();
Работает на уровне конкретного выражения.
Различие:
sideEffects — декларация уровня модуля или пакета/*#__PURE__*/ — точечная аннотация для AST-узлаОни могут комбинироваться, усиливая tree-shaking.
Хотя аннотация изначально связана с Rollup, она активно используется минификаторами, такими как Terser.
При наличии PURE-комментария минификатор может:
Пример трансформации:
Исходный код:
const x = /*#__PURE__*/ create();
После оптимизации:
// удалено полностью, если x не используется
Ошибочное применение аннотации приводит к логическим багам.
const el = /*#__PURE__*/ document.createElement('div');
document.body.appendChild(el);
Здесь createElement кажется «чистым», но реальный эффект
проявляется позже через appendChild. Удаление первой строки
изменяет поведение программы.
Аннотация может применяться к new выражениям:
const service = /*#__PURE__*/ new ApiService();
Однако корректность зависит от конструктора. Если конструктор:
то аннотация становится некорректной.
В сложных выражениях аннотация применяется к каждому узлу отдельно:
const value = /*#__PURE__*/ wrap( /*#__PURE__*/ transform(input));
Rollup анализирует:
wraptransformКаждый уровень может быть удалён независимо при отсутствии использования результата.
Аннотация /*#__PURE__*/ стала стандартом де-факто в
инструментах сборки Jav * aScript:
@babel/plugin-transform-react-pure-annotations)Современные пайплайны часто вставляют PURE-комментарии автоматически:
Пример:
React.createElement(App, null);
Может быть преобразован в:
/*#__PURE__*/ React.createElement(App, null);
Аннотация полностью статична и не может:
Она существует исключительно на уровне исходного текста и AST.
В Rollup граф модулей строится как ориентированный ациклический граф. PURE-аннотация влияет на поведение узлов в этом графе:
Это позволяет уменьшать размер бандла без изменения логики приложения при корректном использовании аннотаций.
В библиотеках PURE-аннотация применяется особенно активно:
export const utils = /*#__PURE__*/ createUtils();
export const config = /*#__PURE__*/ loadConfig();
export const api = /*#__PURE__*/ buildApiClient();
Причина — максимизация tree-shaking у потребителей библиотеки, где не все экспорты используются одновременно.
Аннотация /*#__PURE__*/ является точечным механизмом
управления поведением статического анализатора, позволяя уточнять
границы побочных эффектов и усиливать эффективность tree-shaking в
Rollup-сборках, особенно в условиях сложных графов зависимостей и
библиотечных архитектур.