Поле resolve и поле context

Система разрешения модулей в Rollup определяет, каким образом строки импорта преобразуются в реальные файлы и модули, участвующие в графе зависимостей. На этом этапе формируется структура всего бандла, и именно здесь задаётся, как интерпретируются пути, алиасы, пакеты из node_modules и виртуальные модули плагинов. Поля resolve и context относятся к базовой конфигурации механизма загрузки модулей и влияют на стабильность и предсказуемость сборки.


Контекст выполнения модулей: context

Поле context задаёт значение this для всех модулей, обрабатываемых Rollup в рамках бандла. Оно определяет глобальный контекст исполнения, который используется при оборачивании модулей в функцию.

По умолчанию Rollup использует значение:

this === undefined

в строгом режиме (strict mode), что соответствует поведению ES-модулей.

Основные сценарии использования context

Изменение context требуется в случаях, когда код рассчитан на определённую среду выполнения и использует неявный this.

Пример конфигурации:

export default {
  context: 'window'
};

В этом случае каждый модуль будет обёрнут так, что this указывает на глобальный объект браузера.


Влияние на совместимость

Некоторые старые библиотеки, особенно написанные до широкого распространения ES-модулей, полагаются на глобальный this. Например:

  • использование this вместо window
  • доступ к глобальным переменным через this
  • выполнение кода в нестрогом режиме

При стандартном поведении Rollup такие конструкции могут ломаться, поэтому изменение context становится способом обеспечить совместимость без переписывания исходного кода.


Особенности поведения

Значение context применяется на этапе генерации кода, а не на этапе анализа. Это означает:

  • граф модулей не изменяется
  • трансформация затрагивает только обёртку модулей
  • влияние ограничено runtime-окружением

При этом context не влияет на:

  • разрешение импортов
  • tree-shaking
  • анализ зависимостей

Механизм разрешения модулей: resolve

В конфигурации Rollup напрямую отсутствует базовое поле resolve, однако термин используется для описания всей подсистемы разрешения модулей, которая формируется через плагины, прежде всего через @rollup/plugin-node-resolve.

Фактически resolve в контексте Rollup — это концептуальный слой, определяющий стратегию поиска модулей по строкам импортов.


Базовый процесс resolution

Каждый импорт проходит через несколько этапов:

  1. Анализ строки импорта
  2. Определение типа пути (относительный, абсолютный, пакетный)
  3. Поиск файла в файловой системе
  4. Применение плагинов resolution
  5. Кэширование результата

Роль @rollup/plugin-node-resolve

Основной инструмент, реализующий поведение resolve, — плагин Node Resolve:

import resolve from '@rollup/plugin-node-resolve';

export default {
  plugins: [
    resolve()
  ]
};

Он добавляет поддержку:

  • модулей из node_modules
  • поля exports в package.json
  • расширений .js, .json, .ts
  • browser/ESM полей пакетов
  • алиасов и fallback-логики

Приоритеты разрешения модулей

При обработке импорта Rollup и плагины следуют строгой иерархии:

1. Встроенные и виртуальные модули

Если плагин возвращает модуль как виртуальный (id с собственным содержимым), он имеет приоритет над файловой системой.

2. Алиасы

Если используется плагин alias, например:

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

alias({
  entries: [
    { find: '@', replacement: './src' }
  ]
});

строка импорта преобразуется до этапа файлового поиска.

3. Пакеты node_modules

Плагин node-resolve ищет:

  • package.json
  • поле module
  • поле main
  • поле exports (если включено)
  • fallback на index-файлы

4. Относительные пути

Обрабатываются напрямую через файловую систему:

import x from './utils.js';

Поле context и влияние на resolution

Хотя context напрямую не связан с разрешением модулей, он косвенно влияет на runtime-ожидания кода.

В частности:

  • библиотеки, использующие глобальный this, могут ожидать наличие глобальных объектов
  • UMD-модули могут вести себя по-разному в зависимости от окружения

Однако сам процесс resolve остаётся неизменным.


Расширенная логика resolution в плагинах

Плагины могут полностью переопределять механизм разрешения через resolveId.

Пример:

export default function myResolver() {
  return {
    resolveId(source) {
      if (source === 'virtual-module') {
        return source;
      }
      return null;
    }
  };
}

Возвращаемое значение resolveId определяет:

  • путь к модулю
  • или указание на виртуальный модуль
  • или null, если нужно передать управление следующему плагину

Особенности взаимодействия resolve и кеширования

Rollup активно кеширует результаты resolution:

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

Ошибки в resolution часто связаны с:

  • нестабильными путями
  • динамическими resolveId
  • различиями платформ (browser/node)

Режимы разрешения в node-resolve

Плагин поддерживает несколько режимов:

browser

Используется для фронтенда:

  • приоритет browser field в package.json
  • замена Node API на браузерные аналоги

module

Приоритет ES модулей:

  • поле module
  • ESM-совместимые версии библиотек

main

Fallback:

  • классическое поле main

Поле context в связке с форматами вывода

Разные форматы бандла могут по-разному интерпретировать this:

  • esmthis всегда undefined
  • cjs — зависит от обёртки
  • iife — может указывать на window или global

При этом context задаёт начальную точку поведения, но итог зависит от формата вывода.


Типичные ошибки при неправильной настройке resolution

1. Дублирование модулей

Возникает при:

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

2. Неожиданные версии зависимостей

При использовании нескольких node_modules уровней

3. Конфликты exports

Современные пакеты могут ограничивать доступ к внутренним путям через exports, что ломает старые схемы resolution


Взаимодействие resolution с tree-shaking

Resolution напрямую влияет на tree-shaking:

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

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

Хотя context выглядит как второстепенная настройка, он формирует фундамент модели исполнения:

  • определяет глобальный объект
  • влияет на поведение legacy-кода
  • задаёт базовую семантику this внутри модулей

В связке с resolution он участвует в формировании финальной среды, в которой будет работать собранный код.