@rollup/plugin-inject

@rollup/plugin-inject — это официальный плагин экосистемы Rollup, предназначенный для автоматической подстановки импортов зависимостей в местах их использования. Его основная задача заключается в том, чтобы избавить код от необходимости явно писать import для часто используемых глобальных идентификаторов, библиотек или утилит, заменяя их на соответствующие импорты во время сборки.

Плагин особенно полезен в проектах, где исторически использовались глобальные переменные (например, Promise, fetch, process, $, _) или когда необходимо обеспечить совместимость кода между различными средами выполнения без ручного управления импортами.


Механизм работы @rollup/plugin-inject основан на анализе AST (Abstract Syntax Tree) кода. Плагин отслеживает использование указанных идентификаторов и автоматически добавляет соответствующие импорты в модуль.

Принцип можно описать следующим образом:

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

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


Установка

Плагин устанавливается стандартным способом через npm или yarn:

npm install @rollup/plugin-inject --save-dev

или

yarn add @rollup/plugin-inject -D

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


Базовая конфигурация

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

import inject from '@rollup/plugin-inject';

export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'esm'
  },
  plugins: [
    inject({
      $: 'jquery',
      _: 'lodash'
    })
  ]
};

В этом примере:

  • использование $ автоматически заменяется импортом из jquery;
  • _ подставляется из lodash.

Таким образом, при встрече кода:

$('.app').hide();

Rollup преобразует его примерно в:

import $ from 'jquery';

$('.app').hide();

Множественные экспорты и именованные импорты

Плагин поддерживает более сложные сценарии, включая именованные экспорты.

inject({
  map: ['lodash', 'map'],
  reduce: ['lodash', 'reduce']
});

Здесь происходит следующее:

  • map импортируется как именованный экспорт из lodash;
  • reduce аналогично подтягивается из того же пакета.

Результирующая трансформация:

import { map, reduce } from 'lodash';

Использование с различными типами модулей

@rollup/plugin-inject корректно работает с форматами:

  • ES modules (ESM);
  • CommonJS;
  • смешанными конфигурациями.

В случае CommonJS-пакетов плагин адаптирует импорт:

inject({
  fs: 'fs'
});

В итоге может быть сгенерирован require:

const fs = require('fs');

в зависимости от настроек Rollup и целевого формата сборки.


Поддержка выражений и фабричных функций

Плагин допускает более гибкую настройку через функции, возвращающие модули или конкретные экспорты.

inject({
  dayjs: () => 'dayjs'
});

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


Глубокая интеграция с AST

Внутренне плагин работает через анализ следующих узлов:

  • Identifier
  • MemberExpression
  • CallEx * pression (частично)
  • ImportDeclaration (для избежания конфликтов)

Основная логика:

  1. сбор всех используемых идентификаторов;
  2. проверка совпадения с конфигурацией inject;
  3. определение контекста (локальная переменная или внешняя зависимость);
  4. вставка импортов в начало модуля.

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


Приоритет локальных объявлений

Одна из ключевых особенностей — защита от перезаписи локальных переменных.

inject({
  $: 'jquery'
});

function test() {
  const $ = () => {};
  $('.app');
}

В этом случае:

  • локальный $ внутри функции не будет заменён;
  • глобальный $ вне локальной области будет обработан.

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


Совместимость с tree-shaking

Плагин генерирует явные импорты, что позволяет Rollup применять tree-shaking на уровне модулей.

Однако эффективность зависит от:

  • структуры подключаемых библиотек;
  • наличия side effects;
  • типа экспорта (ESM vs CJS).

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


Расширенные сценарии использования

Автоматическая подстановка polyfill-ов

inject({
  Promise: 'es6-promise'
});

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


Интеграция с legacy-кодом

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

function init() {
  console.log(_VERSION);
}

Плагин позволяет привязать _VERSION к внешнему модулю:

inject({
  _VERSION: ['app-config', 'VERSION']
});

Подмена глобальных утилит

inject({
  fetch: 'cross-fetch'
});

Позволяет унифицировать поведение API в Node.js и браузере.


Ограничения плагина

Несмотря на удобство, @rollup/plugin-inject имеет ряд ограничений:

  • не работает с динамическими идентификаторами;
  • не может анализировать runtime-значения;
  • не заменяет полноценную систему зависимостей;
  • может усложнить отладку из-за скрытых импортов;
  • требует осторожности при использовании в больших кодовых базах.

Влияние на читаемость кода

Использование плагина изменяет философию явных импортов. Код становится короче, но:

  • зависимости становятся неочевидными;
  • возрастает зависимость от конфигурации сборщика;
  • сложнее анализировать происхождение идентификаторов без знания Rollup-конфигурации.

Поэтому его применение обычно ограничивается:

  • legacy-проектами;
  • интеграцией сторонних библиотек;
  • временными миграциями на ESM;
  • полифиллами и глобальными утилитами.

Поведение при конфликтующих правилах

Если один и тот же идентификатор указан несколько раз или пересекается с импортами, Rollup применяет следующие правила:

  • локальные импорты имеют приоритет;
  • явно объявленные import не переопределяются;
  • inject применяется только к необъявленным символам.

Взаимодействие с другими плагинами

@rollup/plugin-inject часто используется вместе с:

  • @rollup/plugin-node-resolve — для поиска модулей;
  • @rollup/plugin-commonjs — для поддержки CJS зависимостей;
  • @rollup/plugin-replace — для замены констант и окружений.

Порядок подключения плагинов влияет на результат трансформации. Обычно inject размещается после node-resolve, но до финальной оптимизации бандла.


Типичные ошибки конфигурации

Неправильная настройка часто приводит к неожиданному поведению:

  • конфликт имен с локальными переменными;
  • случайная подстановка глобальных идентификаторов;
  • дублирование импортов;
  • избыточный размер бандла из-за неиспользуемых inject-правил.

Особенно критична ситуация, когда inject применяется к широко используемым именам вроде map, filter, Promise, что может привести к непредсказуемым импортам в разных частях проекта.


Практическое значение в экосистеме Rollup

@rollup/plugin-inject занимает нишу инструмента автоматизации миграций и упрощения поддержки старого кода. Его роль не заключается в построении архитектуры модулей, а в мосте между:

  • глобальным JavaScript;
  • модульным ESM-кодом;
  • legacy CommonJS-библиотеками.

Это делает его вспомогательным, но важным компонентом в сложных сборочных цепочках Rollup.