Parcel использует модульную систему расширений, основанную на строгом разделении ответственности между типами плагинов. Каждый тип плагина отвечает за отдельный этап обработки модуля или всего графа зависимостей. Такая архитектура позволяет строить предсказуемый и масштабируемый пайплайн сборки, где поведение легко расширяется без изменения ядра сборщика.
Плагинная система Parcel строится вокруг нескольких ключевых точек расширения:
Каждый тип плагина взаимодействует с конкретной фазой графа модулей, что исключает пересечение обязанностей и снижает сложность расширений.
Transformer-плагины являются одной из центральных точек расширения Parcel. Они отвечают за преобразование содержимого модулей до того, как код попадёт в этап упаковки.
Transformer выполняет следующие операции:
Transformer работает на уровне содержимого файла, а не графа зависимостей.
Parcel передаёт Transformer-плагину объект модуля, содержащий:
Плагин возвращает преобразованный код и дополнительные зависимости.
export default function transformer({ asset }) {
if (asset.type === 'js') {
const transformed = compileToES5(asset.code);
asset.setCode(transformed);
}
if (asset.type === 'css') {
const result = compileSass(asset.code);
asset.setCode(result.css);
asset.addDependencies(result.imports);
}
}
Transformer — наиболее часто используемый тип плагинов, поскольку именно он отвечает за совместимость исходного кода с целевой средой.
Resolver-плагины отвечают за определение реального местоположения импортируемых модулей. Они участвуют в процессе построения графа зависимостей.
Resolver работает до загрузки содержимого модуля, на этапе анализа ссылок.
При встрече импорта:
import utils from "@lib/utils";
Resolver выполняет цепочку операций:
export default function resolver({ dependency }) {
if (dependency.specifier.startsWith('@lib/')) {
return {
filePath: dependency.specifier.replace('@lib/', './src/lib/')
};
}
return null;
}
Resolver обеспечивает гибкость архитектуры проекта, позволяя абстрагироваться от физического расположения файлов.
Packager-плагины отвечают за объединение модулей в итоговые файлы. Это стадия, где граф зависимостей превращается в физический артефакт.
Packager работает с уже полностью построенным графом.
Parcel передаёт Packager:
Packager формирует текстовый или бинарный результат.
export default function packager({ bundle }) {
let output = '';
for (const asset of bundle.assets) {
output += `// ${asset.id}\n`;
output += asset.generatedCode + '\n';
}
return output;
}
Packager является завершающей стадией формирования артефакта до оптимизации.
Optimizer-плагины применяются после упаковки и отвечают за улучшение качества и производительности итогового кода.
Optimizer работает с уже готовыми бандлами.
Optimizer получает:
И возвращает оптимизированную версию.
export default function optimizer({ bundle }) {
if (bundle.type === 'js') {
bundle.code = minifyJS(bundle.code);
}
if (bundle.type === 'css') {
bundle.code = minifyCSS(bundle.code);
}
}
Optimizer влияет на производительность загрузки и выполнения приложения.
Reporter-плагины предназначены для сбора и отображения информации о процессе сборки. Они не влияют на код, но управляют наблюдаемыми данными.
Reporter работает параллельно с остальными стадиями.
Parcel генерирует события:
Reporter подписывается на эти события.
export default function reporter({ event }) {
if (event.type === 'buildStart') {
console.log('Сборка началась');
}
if (event.type === 'buildError') {
console.error(event.error);
}
if (event.type === 'buildSuccess') {
console.log('Сборка завершена');
}
}
Reporter играет ключевую роль в наблюдаемости процесса сборки.
Namer-плагины отвечают за генерацию имён файлов в итоговом бандле. Они определяют, как будут называться артефакты на диске.
Namer работает на этапе формирования финального результата.
Parcel передаёт Namer:
Плагин возвращает строку пути.
export default function namer({ bundle }) {
if (bundle.type === 'js') {
return `dist/${bundle.name}.${bundle.hash}.js`;
}
if (bundle.type === 'css') {
return `dist/styles.${bundle.hash}.css`;
}
return `dist/${bundle.name}`;
}
Namer завершает процесс формирования структуры выходных файлов, обеспечивая стабильную и предсказуемую систему хранения артефактов.