Фаза moduleParsed выполняется в момент, когда Rollup завершает разбор модуля в абстрактное синтаксическое дерево (AST) и сформировал базовую структуру информации о модуле. На этом этапе модуль уже загружен, пропущен через load и transform (если они были задействованы), и его содержимое приведено к финальному виду, который будет использоваться в графе зависимостей.
Хук вызывается для каждого модуля, включённого в граф сборки:
moduleParsed(id, moduleInfo)
id — абсолютный путь к модулю (или виртуальный
идентификатор)moduleInfo — объект с метаданными о модуле, формируемый
RollupХук синхронный по своей природе в архитектуре вызовов графа, но может
возвращать Promise, если требуется асинхронная
обработка.
Ключевой момент: вызов происходит после парсинга AST, но до окончательной фиксации графа зависимостей и оптимизаций tree-shaking.
Пайплайн обработки модуля в Rollup можно упростить до последовательности:
loadtransformmoduleParsedТаким образом, moduleParsed является точкой, где:
moduleInfo.astЭто делает хук особенно ценным для анализа структуры модуля, но не для изменения исходного кода.
Объект moduleInfo содержит широкий набор данных:
code — итоговый код модуля после transformast — ESTree-совместимое деревоimports — список импортовexports — экспортируемые сущностиhasDefaultExport — наличие default exportisEntry — является ли модуль входной точкойmoduleSideEffects — информация о побочных эффектахОднако важное ограничение заключается в том, что:
Изменение moduleInfo внутри moduleParsed не влияет на уже построенный AST или граф зависимостей.
Любые попытки модифицировать структуру модуля на этом этапе являются либо игнорируемыми, либо приводят к неочевидному поведению.
moduleParsed применяется в случаях, когда необходимо анализировать уже разобранный модуль:
Наиболее распространённый сценарий — инспекция AST:
export default function myPlugin() {
return {
name: 'analyzer',
moduleParsed(id, info) {
if (info.ast && info.ast.body) {
const functionDeclarations = info.ast.body.filter(
node => node.type === 'FunctionDeclaration'
);
if (functionDeclarations.length > 5) {
// логирование или метрики
}
}
}
};
}
Хук часто используют для построения внешних индексов модулей:
Возможна проверка архитектурных правил:
Ключевая ошибка при использовании Rollup-плагинов — путаница между transform и moduleParsed.
Ключевое различие:
transform влияет на входные данные, moduleParsed — наблюдает результат
Одним из ключевых преимуществ moduleParsed является доступ к AST:
moduleParsed(id, info) {
const ast = info.ast;
}
AST в Rollup:
Однако AST может быть null в случаях:
На момент вызова moduleParsed:
Это даёт возможность использовать API:
this.getModuleInfo(id)
или анализировать связи через
moduleInfo.importedIds.
Однако важно учитывать:
Хотя хук чаще используется синхронно, поддержка Promise позволяет выполнять тяжёлые операции:
moduleParsed(id, info) {
return someAsyncAnalysis(info.ast).then(result => {
// сохранение результатов
});
}
При этом Rollup не блокирует весь пайплайн, но учитывает завершение Promise перед финализацией сборки.
Любые попытки изменить info.code или
info.ast не приводят к изменениям в сборке.
Так как хук вызывается для каждого модуля:
Некоторые данные уже доступны в transform, поэтому дублирование анализа в moduleParsed часто избыточно.
Корректное использование обычно выглядит так:
export default function plugin() {
const cache = new Map();
return {
name: 'module-analyzer',
moduleParsed(id, info) {
cache.set(id, {
imports: info.imports,
exports: info.exports,
hasDefault: info.hasDefaultExport
});
},
buildEnd() {
// использование накопленных данных
}
};
}
Такой подход позволяет:
moduleParsed занимает промежуточное положение между:
Его основная ценность заключается в том, что он предоставляет стабильную точку наблюдения за уже разобранным модулем, не вмешиваясь в процесс его трансформации.