Хук banner, footer, intro, outro

В процессе сборки Rollup финальный бандл проходит стадию генерации выходного кода, где подключаются специальные плагины и формируется итоговая строка/модули. На этом этапе ключевую роль играют хуки, позволяющие вмешаться в структуру результирующего файла: intro, banner, footer, outro.

Эти хуки относятся к категории output generation hooks и выполняются при создании финального чанка или бандла. Их основная задача — модифицировать текстовое содержимое результата без изменения графа модулей.


Общая модель формирования выходного кода

При генерации бандла Rollup формирует итоговую структуру примерно в таком порядке:

  1. banner
  2. intro
  3. основной сгенерированный код
  4. outro
  5. footer

Каждый из этих слоёв представляет собой строковую вставку, которая может быть добавлена в начало или конец итогового файла.

Важно учитывать, что все эти хуки работают на уровне строкового представления чанка и не влияют на структуру модулей, импортов или зависимостей.


Хук banner

Назначение

banner добавляет текст в самое начало выходного файла, перед любым сгенерированным кодом Rollup.

Чаще всего используется для:

  • лицензий
  • копирайтов
  • метаданных о сборке
  • комментариев верхнего уровня

Сигнатура

banner: string | (() => string | Promise<string>)

Поведение

  • выполняется на этапе генерации output
  • может возвращать строку или Promise
  • добавляется до intro

Пример использования

export default {
  output: {
    banner: '/* Built with Rollup */'
  }
};

Функциональный вариант:

export default {
  output: {
    banner() {
      return `/* Build time: ${new Date().toISOString()} */`;
    }
  }
};

Особенности

  • не влияет на tree-shaking
  • не оборачивает код
  • не модифицирует модули
  • добавляется только в финальный чанк

Хук intro

Назначение

intro вставляет код сразу после banner, но до основного содержимого бандла.

Используется для:

  • объявления глобальных переменных
  • setup-кода
  • polyfill-инициализаций
  • ранней конфигурации окружения

Сигнатура

intro: string | (() => string | Promise<string>)

Пример

export default {
  output: {
    intro: 'const __ENV__ = "production";'
  }
};

Функция:

export default {
  output: {
    intro() {
      return 'const start = Date.now();';
    }
  }
};

Поведение

  • выполняется после banner
  • вставляется до всех модулей
  • может содержать исполняемый JS-код
  • поддерживает динамическую генерацию

Хук outro

Назначение

outro добавляет код после основного содержимого бандла, но до footer.

Применяется для:

  • закрытия IIFE-обёрток
  • финализации состояния
  • логирования завершения выполнения
  • добавления вспомогательных экспорто-зависимых конструкций

Сигнатура

outro: string | (() => string | Promise<string>)

Пример

export default {
  output: {
    outro: 'console.log("bundle loaded");'
  }
};

Функциональный вариант:

export default {
  output: {
    outro() {
      return 'console.log("end of execution");';
    }
  }
};

Особенности

  • выполняется после основного кода модулей
  • может взаимодействовать с глобальными переменными, созданными в intro
  • часто используется в паре с intro для симметричных конструкций

Назначение

footer добавляет код в самый конец выходного файла.

Используется для:

  • закрывающих комментариев
  • финальных метаданных
  • завершающих инструкций
  • подведения итогов сборки на уровне кода

Сигнатура

footer: string | (() => string | Promise<string>)

Пример

export default {
  output: {
    footer: '/* End of bundle */'
  }
};

Функция:

export default {
  output: {
    footer() {
      return `/* Generated at ${new Date().toISOString()} */`;
    }
  }
};

Порядок выполнения и композиция

Полная структура итогового файла с использованием всех хуков выглядит так:

banner
intro
[сгенерированный Rollup код]
outro
footer

Важные моменты композиции

  • banner и footer — внешние мета-слои
  • intro и outro — внутренние слои вокруг логики
  • порядок фиксирован и не может быть изменён
  • хуки не пересекаются и не конфликтуют между собой напрямую

Контекст выполнения и особенности API

Все четыре хука поддерживают одинаковую модель:

  • строка как результат
  • функция, возвращающая строку
  • асинхронная функция (Promise)

Это позволяет динамически формировать содержимое в зависимости от состояния сборки.

Пример с асинхронностью

export default {
  output: {
    banner: async () => {
      const version = await fetchVersion();
      return `/* version: ${version} */`;
    }
  }
};

Различия между хуками

  • banner — начало файла
  • footer — конец файла
  • оба используются для метаинформации

intro vs outro

  • intro — подготовка окружения
  • outro — завершение выполнения
  • чаще образуют логическую пару

Практические сценарии использования

Оборачивание в IIFE

export default {
  output: {
    intro: '(function(){',
    outro: '})();'
  }
};

Добавление окружения выполнения

export default {
  output: {
    intro: `
      const __DEV__ = false;
      const __VERSION__ = "1.0.0";
    `
  }
};

Метаданные сборки

export default {
  output: {
    banner: '/* library build */',
    footer: '/* eof */'
  }
};

Логирование выполнения

export default {
  output: {
    intro: 'console.log("start");',
    outro: 'console.log("finish");'
  }
};

Ограничения и поведение при минификации

При использовании минификаторов (Terser, SWC и др.):

  • хуки остаются неизменными
  • содержимое вставляется до минификации или после неё в зависимости от пайплайна
  • Rollup не анализирует код внутри хуков

Важно учитывать, что строки из banner и footer могут сохраняться даже в сильно оптимизированных сборках.


Влияние на формирование чанков

Каждый чанк получает собственные значения этих хуков. Это означает:

  • можно формировать разные banner для разных output chunks
  • intro и outro могут различаться по логике для каждого файла
  • Rollup вызывает хуки на уровне генерации каждого output

Функциональная модель использования

На уровне плагинов эти хуки могут быть определены через plugin API:

export default function myPlugin() {
  return {
    name: 'my-plugin',

    banner() {
      return '/* plugin banner */';
    },

    intro() {
      return 'console.log("intro");';
    },

    outro() {
      return 'console.log("outro");';
    },

    footer() {
      return '/* plugin footer */';
    }
  };
}

Особенности взаимодействия нескольких плагинов

Если несколько плагинов определяют один и тот же хук:

  • значения объединяются
  • порядок зависит от порядка подключения плагинов
  • итоговый результат может быть конкатенацией строк

Контроль генерации итогового текста

Хуки banner, intro, outro, footer фактически формируют каркас итогового JavaScript-файла. Они позволяют:

  • управлять внешней оболочкой бандла
  • добавлять системные вставки
  • формировать среду выполнения без изменения модулей
  • влиять на поведение кода на уровне структуры файла