В Parcel воркеры рассматриваются как полноценные точки входа, для
которых формируется отдельный граф зависимостей и независимый набор
чанков. Это означает, что код, выполняемый в Web Worker, не
просто выносится в отдельный файл, а проходит тот же процесс анализа,
трансформации и оптимизации, что и основной поток приложения.
Ключевое отличие заключается в изоляции бандлов: worker не разделяет runtime-окружение с главным потоком, поэтому Parcel строит для него отдельное дерево модулей, учитывая специфику загрузки и взаимодействия через сообщения.
В Parcel любой worker-файл автоматически становится самостоятельным entry point при его создании через стандартный API браузера:
const worker = new Worker(
new URL('./worker.js', import.meta.url),
{ type: 'module' }
);
Parcel анализирует конструкцию
new URL(..., import.meta.url) и определяет
worker.js как отдельный граф сборки. В результате:
Такой подход исключает необходимость использования специализированных loader’ов, характерных для более старых сборщиков.
При анализе worker-файла Parcel строит изолированный dependency graph. Это означает, что:
Пример структуры:
main bundle
├── index.js
├── ui.js
└── shared.js
worker bundle
├── worker.js
├── compute.js
└── shared.js (возможен вынос в общий chunk)
Parcel применяет эвристики для дедупликации кода, если модули используются в обоих контекстах.
Разделение кода в worker-контексте особенно эффективно при
использовании import():
self.addEventListener('message', async (event) => {
const { heavyTask } = await import('./heavyTask.js');
const result = heavyTask(event.data);
self.postMessage(result);
});
Parcel воспринимает динамический импорт как сигнал для code splitting и формирует отдельный async chunk внутри worker-bundle.
Особенности поведения:
import();Worker-контекст накладывает ограничения на характер разделяемых модулей:
window или
document.Parcel не пытается «исправлять» такие зависимости, а оставляет их на уровне ошибок сборки или runtime, сохраняя предсказуемость графа.
В результате разделение кода в worker требует чистого разделения слоёв архитектуры: вычислительная логика должна быть отделена от интерфейсной.
Parcel поддерживает вынос повторяющихся модулей в shared chunks. Если один и тот же модуль используется:
он может быть вынесен в общий фрагмент при соблюдении условий:
window,
document);Однако в случае worker это поведение ограничено, так как изолированность контекстов часто делает разделение менее агрессивным, чем в браузерном основном бандле.
После сборки Parcel формирует отдельный файл worker-bundle, который загружается браузером по стандартному механизму:
Worker;Важно, что runtime worker-а не разделяет состояние с главным приложением. Даже если используются одинаковые модули, их экземпляры существуют независимо.
Разделение кода внутри worker-контекста напрямую влияет на производительность:
Типичный сценарий:
// worker.js
self.onmess age = async ({ data }) => {
if (data.type === 'FFT') {
const { fft } = await import('./math/fft.js');
self.postMessage(fft(data.payload));
}
};
Parcel создаёт отдельный chunk для fft.js, который
загружается только при необходимости выполнения вычислений.
Parcel анализирует повторное использование модулей между чанками worker-а и применяет следующие стратегии:
Это особенно эффективно в проектах, где worker выполняет разные типы задач (например, обработка изображений, криптография, вычисления).
Parcel генерирует отдельные source maps для worker-бандлов. Это обеспечивает:
Каждый chunk worker-а имеет собственную карту соответствий, что позволяет локализовать ошибки без влияния основного бандла.
Hot Module Replacement в worker-окружении имеет ограничения:
В результате поведение HMR в worker ближе к полной перезагрузке контекста, чем к инкрементальному обновлению.
Разделение кода в worker-контексте предполагает строгое взаимодействие через message-passing:
// main.js
worker.postMessage({ type: 'PROCESS', payload: data });
worker.onmess age = (event) => {
console.log(event.data);
};
Parcel не вмешивается в этот механизм, но обеспечивает корректную сборку обоих концов взаимодействия.
Архитектурно это усиливает разделение ответственности:
В процессе работы с Parcel и worker-контекстом часто возникают следующие проблемы:
Parcel фиксирует часть таких ошибок на этапе сборки, но многие проявляются только во время выполнения.
Рациональная структура worker-кода в Parcel обычно строится по принципам:
Такая структура усиливает эффективность code splitting и снижает стоимость инициализации worker-бандла.
Parcel применяет файловое хеширование к каждому worker chunk:
Это делает worker-контекст устойчивым к частым пересборкам в production и снижает сетевую нагрузку при повторных запусках приложения.