Хук resolveId является одним из ключевых механизмов
системы плагинов Rollup, определяющим, как сборщик находит и
интерпретирует модули во время построения графа зависимостей. Именно на
этом этапе формируется структура всего бандла, так как каждая
зависимость проходит процесс разрешения пути, переопределения или полной
подмены.
Во время анализа входной точки Rollup последовательно обходит импорты
и для каждого выражения вида import ... from '...'
запускает цепочку разрешения идентификатора модуля. В этот процесс может
вмешиваться плагин через resolveId, изменяя стандартное
поведение.
Основная задача хука — преобразование строкового идентификатора импорта в:
external)Именно здесь решается, будет ли модуль включён в бандл, заменён или проигнорирован.
Хук resolveId имеет следующую логическую форму:
resolveId(source, importer, options)
Где:
source — строка импорта, указанная в коде
('react', './utils', 'fs')importer — путь к модулю, из которого выполняется
импортoptions — дополнительные параметры разрешения
(например, условия Node ESM)Возвращаемое значение определяет дальнейшее поведение Rollup:
string — новый путь к модулю{ id, external } — объект с явным указанием внешней
зависимостиnull или undefined — передача управления
следующему резолверуВсе плагины с реализацией resolveId выстраиваются в
строгую последовательность. Rollup вызывает их по очереди до тех пор,
пока один из них не вернёт ненулевой результат.
Порядок обработки:
Если один плагин возвращает значение, цепочка может быть прервана, и
дальнейшие resolveId не вызываются.
Одной из наиболее распространённых задач resolveId
является подмена модулей. Это используется для:
Пример логики:
export default function myPlugin() {
return {
name: 'my-plugin',
resolveId(source) {
if (source === 'env') {
return '\0virtual:env';
}
return null;
}
};
}
Здесь строка env заменяется на виртуальный модуль,
идентифицируемый префиксом \0, который Rollup трактует как
внутренний.
Rollup поддерживает концепцию виртуальных модулей — сущностей, не существующих в файловой системе. Они создаются исключительно через плагины.
Для их обозначения часто используется соглашение:
\0 префикс — внутренний модуль Rollupvirtual: — семантический неймингresolveId в этом случае играет роль генератора
идентификатора:
resolveId(source) {
if (source === 'config') {
return '\0virtual:config';
}
}
Далее этот идентификатор обрабатывается через load.
Хук может явно помечать модуль как внешний, исключая его из бандла:
resolveId(source) {
if (source === 'lodash') {
return { id: 'lodash', external: true };
}
}
Это позволяет:
Rollup не будет пытаться разрешать или включать такой модуль в граф.
Внутри resolveId часто реализуется логика различения
типов импортов:
./, ../react, lodash@src/utilsПример обработки алиасов:
resolveId(source) {
if (source.startsWith('@src/')) {
return source.replace('@src/', '/project/src/');
}
}
Такая логика позволяет реализовывать систему псевдонимов без участия внешних инструментов.
resolveId может быть асинхронным, что важно при:
async resolveId(source) {
const result = await fetchConfig(source);
return result?.path || null;
}
Асинхронность интегрируется в общий pipeline Rollup без блокировки сборки.
Второй аргумент importer критически важен для
контекстного разрешения:
Пример:
resolveId(source, importer) {
if (source === './config') {
if (importer.includes('admin')) {
return '/config/admin.js';
}
return '/config/default.js';
}
}
Таким образом один и тот же импорт может вести к разным модулям в зависимости от контекста.
Третий аргумент options содержит дополнительные
параметры, связанные с резолвингом:
conditions)Это позволяет адаптировать поведение под Node.js ESM-алгоритм или кастомные среды.
Пример использования:
resolveId(source, importer, options) {
if (options?.isEntry) {
return `/entry/${source}`;
}
}
Каждый результат resolveId напрямую влияет на структуру
dependency graph:
external исключает вершинуОшибки на этом этапе приводят к:
resolveId почти всегда используется совместно с
load:
resolveId определяет идентификаторload возвращает содержимое модуляТипичный сценарий виртуального модуля:
resolveId() -> '\0virtual:data'
load(id) -> 'export const data = 42;'
Возврат null имеет особое значение: он не прерывает
цепочку и позволяет другим плагинам обработать импорт. Это основной
механизм кооперации плагинов.
Возврат строки или объекта, наоборот, фиксирует результат и завершает резолвинг.
resolveId фактически определяет, как Rollup воспринимает
мир модулей:
Через этот хук реализуются:
Он находится в начале цепочки трансформации и задаёт фундамент всей последующей обработки модулей.