Хук transform является одним из ключевых механизмов
системы плагинов Rollup и предназначен для изменения содержимого модулей
на этапе их обработки. Этот хук позволяет перехватывать исходный код
каждого модуля после его загрузки и до анализа зависимостей, что делает
его центральной точкой для трансформации кода, внедрения дополнительных
инструкций, переписывания синтаксиса и реализации пользовательских
расширений компиляционного процесса.
Этап transform располагается после получения исходного
содержимого модуля и до построения графа зависимостей в окончательном
виде. Последовательность обработки модуля в Rollup можно описать
следующим образом:
resolveId)load)transform)Таким образом, transform работает с уже загруженным
кодом, но до того, как Rollup окончательно зафиксирует структуру
зависимостей. Это делает хук критически важным для любых операций,
влияющих на синтаксис или структуру модулей.
Хук transform может быть синхронным или асинхронным и
принимает два основных параметра:
code — строка с исходным кодом модуля после
загрузкиid — уникальный идентификатор модуля (обычно абсолютный
путь)Дополнительно может возвращаться объект с полями:
code — изменённый кодmap — sourcemap для корректного отображения исходного
кодаПример логической структуры:
transform(code, id) {
return {
code: modifiedCode,
map: sourceMap
};
}
Асинхронный вариант:
async transform(code, id) {
const result = await process(code);
return {
code: result.code,
map: result.map
};
}
Одна из наиболее распространённых задач — преобразование нестандартного или экспериментального синтаксиса в совместимый JavaScript. Это может включать:
На этом этапе Rollup не ограничивает тип трансформации, поэтому хук часто используется как основа для компиляторов.
transform позволяет модифицировать модули путем
добавления или изменения логики. Примеры:
transform(code) {
return {
code: `console.log("module loaded");\n${code}`
};
}
Хотя основная работа с импортами происходит в resolveId,
в transform можно изменять строки импортов до анализа, что
позволяет:
Хук может возвращать несколько типов значений:
Если возвращается строка, она интерпретируется как новый код модуля:
transform(code) {
return code.toUpperCase();
}
Используется при необходимости передать source map:
transform(code) {
return {
code: transformed,
map: mapObject
};
}
nullВозвращение null означает отсутствие изменений и
передачу кода дальше по цепочке.
Внутри хука доступен контекст плагина через this,
который предоставляет дополнительные возможности:
this.emitFile — генерация новых файловthis.warn — вывод предупрежденийthis.error — генерация ошибок сборкиthis.getModuleInfo — получение информации о модулеПример использования контекста:
transform(code, id) {
if (code.includes('eval')) {
this.warn(`Использование eval в ${id}`);
}
return code;
}
Поддержка source map является важной частью transform,
так как любые изменения кода должны сохранять корректное отображение
исходных строк.
Основные режимы:
true — автоматическая генерацияfalse — отключение"inline" — встроенная картаКорректная работа с sourcemap критична при цепочках плагинов, где каждый этап трансформирует код.
Rollup может кэшировать результаты transform для
ускорения последующих сборок. Кэширование зависит от:
Если трансформация зависит от внешнего состояния, необходимо явно учитывать это при проектировании плагина, иначе возможно получение устаревших результатов.
Хотя transform не предназначен напрямую для управления
зависимостями, он влияет на их формирование, поскольку Rollup
анализирует импорт-выражения уже после трансформации кода. Это
означает:
Хук имеет ряд архитектурных ограничений:
resolveId)Особенно важно учитывать порядок выполнения: плагины применяются
последовательно, и каждый transform получает результат
предыдущего.
При использовании нескольких плагинов каждый из них может изменять код. Порядок имеет принципиальное значение:
Это позволяет строить цепочки трансформаций, но также создаёт риск конфликтов при несовместимых изменениях.
transform часто используется вместе с виртуальными
модулями, когда код генерируется динамически. В этом случае:
id может не соответствовать файловой системеЭто позволяет реализовывать DSL, конфигурационные модули и динамическую генерацию кода.
Поскольку transform вызывается для каждого модуля, его
производительность напрямую влияет на скорость сборки. Основные
рекомендации архитектурного характера:
В крупных проектах именно transform становится основной
точкой оптимизации сборки.
Хотя Rollup сам по себе не требует работы с AST, большинство трансформаций используют его. Типичный сценарий:
codetransformЭтот подход обеспечивает точечные изменения без разрушения структуры модуля.