Контекст плагина Rollup представляет собой объект, доступный внутри
большинства хуков плагина через this, и содержит набор
низкоуровневых API для взаимодействия с системой сборки. Среди наиболее
важных методов этого контекста находятся this.parse,
this.resolve и this.load, которые позволяют
плагину вмешиваться в этапы анализа, разрешения модулей и загрузки
исходного кода.
В процессе сборки Rollup последовательно обрабатывает модули через
цепочку хуков: resolveId, load,
transform и другие. Однако внутри этих хуков часто
требуется доступ к внутренним механизмам самого бандлера. Контекст
плагина предоставляет такой доступ, позволяя выполнять операции,
аналогичные внутренним шагам Rollup, но в управляемом и расширяемом
виде.
Методы контекста не являются независимыми утилитами — они работают в рамках текущего графа модулей, учитывают кеширование, зависимости и конфигурацию сборки.
Метод this.parse используется для преобразования строки
исходного кода в AST (Abstract Syntax Tree). Это тот же этап, который
Rollup выполняет при анализе модулей, но доступный напрямую внутри
плагина.
Сигнатура:
this.parse(code: string, acornOptions?: object) => ESTree.Program
Основная задача this.parse — дать плагину возможность
анализировать структуру кода без необходимости вручную подключать парсер
(например, Acorn). Rollup использует Acorn под капотом, поэтому
результат соответствует ESTree-совместимому AST.
Это особенно важно для плагинов, которые:
ecmaVersion,
sourceType).Плагин может извлечь все импортируемые модули:
transform(code) {
const ast = this.parse(code);
for (const node of ast.body) {
if (node.type === 'ImportDeclaration') {
console.log(node.source.value);
}
}
}
transform-хук.Метод this.resolve выполняет логическое разрешение
идентификатора модуля в реальный путь или виртуальный идентификатор
внутри графа Rollup. Это аналог внутреннего процесса, который происходит
в resolveId.
Сигнатура:
this.resolve(source: string, importer?: string, options?: object) => Promise<ResolvedId | null>
this.resolve позволяет плагину:
import внутри сборщика.Результатом вызова является объект вида:
{
id: string,
external?: boolean,
resolvedBy?: string
}
или null, если модуль не может быть разрешён.
Учитывает все плагины, участвующие в
resolveId.
Поддерживает опции, влияющие на поведение резолвинга:
skipSelf — исключает текущий плагин из цепочки
разрешения;isEntry — указывает, что модуль является входной
точкой;custom — дополнительные пользовательские
параметры.Часто используется для анализа зависимостей:
async transform(code, id) {
const ast = this.parse(code);
for (const node of ast.body) {
if (node.type === 'ImportDeclaration') {
const resolved = await this.resolve(node.source.value, id);
if (resolved) {
console.log('Resolved:', resolved.id);
}
}
}
}
this.resolve особенно важен при работе с виртуальными
модулями (virtual: схемы), где стандартное файловое
разрешение не применяется.
Метод this.load позволяет программно инициировать
загрузку модуля по его идентификатору, минуя стандартный поток импорта.
Он вызывает соответствующие плагины через load-хук и
возвращает содержимое модуля.
Сигнатура:
this.load(options: { id: string }) => Promise<LoadResult | null>
Основные задачи this.load:
Результат обычно имеет форму:
{
code: string,
map?: SourceMap,
ast?: object
}
или null, если модуль не может быть загружен.
При вызове:
load-хуков плагинов.Часто применяется для построения метаплагинов, анализирующих или модифицирующих другие модули:
async buildStart() {
const result = await this.load({ id: 'src/index.js' });
if (result) {
console.log(result.code);
}
}
load-хуков рекурсивно.Эти три метода формируют базовый инструментарий для построения расширенной логики плагинов:
this.parse отвечает за анализ структуры кода;this.resolve определяет связи между модулями;this.load предоставляет доступ к содержимому модулей
через систему Rollup.Комбинирование этих методов позволяет:
transform(code, id) {
const ast = this.parse(code);
for (const node of ast.body) {
if (node.type === 'ImportDeclaration') {
this.resolve(node.source.value, id).then(resolved => {
if (resolved && !resolved.external) {
console.log(resolved.id);
}
});
}
}
}
async buildStart() {
const entry = await this.resolve('./src/main.js');
if (entry) {
const mod = await this.load({ id: entry.id });
console.log(mod?.code);
}
}
transform(code) {
const ast = this.parse(code);
return null;
}
Комбинация this.load и this.resolve может
приводить к рекурсивным цепочкам загрузки, если плагин некорректно
обрабатывает зависимости.
this.parse — наиболее затратная операция при частом
использовании. При больших проектах повторный парсинг одних и тех же
модулей может заметно замедлять сборку.
Rollup активно кэширует результаты load, но вызовы через
this.load могут обходить некоторые оптимизации, если
используются нестандартные id или виртуальные модули.
this.resolve и this.load зависят от порядка
подключения плагинов, так как цепочка обработки модулей линейна и
приоритетна.
this.parse работает с текущим состоянием кода, но не
учитывает будущие трансформации других плагинов, что может приводить к
расхождениям между AST и финальным кодом.