В Parcel концепция таргетов (targets) определяет, в какие конечные окружения и форматы будет собран проект. Один и тот же исходный код может одновременно транслироваться в несколько независимых выходов: браузерный бандл, Node.js-модуль, ESM-библиотеку или специализированный сборочный формат для встраивания.
Каждый таргет описывает собственный набор параметров: директорию вывода, окружение выполнения, формат модулей, требования к совместимости и дополнительные опции трансформации. При этом Parcel рассматривает таргеты не как простые конфигурации, а как изолированные графы сборки, построенные поверх общего графа исходников.
Такой подход позволяет разделять ответственность между исходным кодом и его конечным представлением, не дублируя логику обработки модулей.
При анализе проекта Parcel строит единый граф модулей, где каждый узел представляет файл или ресурс, а ребра отражают зависимости.
Далее этот граф логически разделяется на подграфы по числу таргетов. Один и тот же модуль может входить сразу в несколько подграфов, если используется в разных выходных сборках.
Ключевая особенность заключается в том, что Parcel не пересобирает граф целиком при каждом изменении. Вместо этого поддерживается связь:
Это позволяет отслеживать влияние изменения не глобально, а локально — только в тех таргетах, где модуль реально используется.
При изменении файла Parcel помечает соответствующий узел графа как инвалидированный. Дальнейшее распространение инвалидности происходит по зависимостям, но только внутри затронутых таргетов.
Если модуль используется в нескольких таргетах, пересчёт выполняется выборочно:
Такой подход уменьшает объём работы при инкрементальной сборке и особенно эффективен в проектах с несколькими выходами (например, библиотека + приложение).
Parcel опирается на многоуровневое кэширование, где результат каждого этапа трансформации фиксируется с учётом входных параметров:
При изменении исходного кода пересчитываются только те узлы, чей хеш больше не совпадает с сохранённым значением. Остальные этапы берутся из кэша без повторного выполнения.
Инкрементальная сборка в сочетании с кэшем позволяет реализовать выборочную пересборку даже в проектах с тысячами модулей, где изменение одной строки кода не приводит к глобальному пересчёту всего выходного результата.
Разные таргеты могут требовать различных преобразований одного и того же исходного кода. Например:
Parcel учитывает эти различия на этапе построения подграфов. В результате один модуль может быть преобразован по-разному в зависимости от контекста использования.
Это означает, что изменение исходного файла может затронуть только один из вариантов трансформации, оставляя остальные нетронутыми.
Процесс пересборки при изменении файла можно описать последовательностью:
Главный принцип заключается в том, что пересборка происходит не по проекту в целом, а по минимально затронутому подмножеству графа, ограниченному конкретными выходными конфигурациями.
В watch-режиме Parcel удерживает граф сборки в памяти и отслеживает изменения файловой системы.
Каждое изменение приводит к локальному пересчёту:
Особенность заключается в том, что даже при множественных изменениях Parcel способен группировать обновления, избегая повторных вычислений для промежуточных состояний.
Таким образом, серия изменений в одном модуле не вызывает повторной полной пересборки всех выходов.
В проектах библиотечного типа часто используются одновременно несколько таргетов:
main для CommonJSmodule для ESMbrowser для клиентского окруженияПри изменении внутреннего модуля библиотеки пересобираются только те таргеты, где модуль включён в итоговую цепочку импортов. Например, Node-таргет может остаться неизменным, если изменение затрагивает только браузерную специфичную часть.
В монорепозиториях эффект усиливается: общие зависимости переиспользуются между пакетами, но пересборка ограничивается только теми пакетами, где произошли изменения, а внутри них — только активными таргетами.
Выборочная сборка тесно связана с механизмом разделения кода. Parcel анализирует граф и выделяет общие зависимости, формируя отдельные чанки.
При изменении модуля происходит пересчёт только тех чанков, которые включают изменённый код или зависят от него. Остальные чанки остаются стабильными, даже если находятся в том же таргете.
Такой подход снижает стоимость пересборки при частых изменениях и минимизирует объём генерируемых артефактов.
Особое значение имеет механизм транзитивной инвалидности. Изменение глубинного модуля может затронуть верхнеуровневые зависимости, но Parcel ограничивает распространение только реально используемыми путями.
Если зависимость присутствует в нескольких таргетах, пересчёт выполняется независимо для каждого контекста. Это предотвращает каскадную пересборку всей системы при локальных изменениях.
Ключевая идея выборочной сборки заключается в том, что результат трансформации модуля зависит от контекста таргета. Поэтому кэш хранится не только по входному файлу, но и по комбинации:
Такой многомерный кэш позволяет повторно использовать результаты даже при сложных конфигурациях, если изменяется только часть системы.
Когда один модуль используется в нескольких таргетах, Parcel анализирует различия их графов. Если изменения затрагивают только один из контекстов, пересборка ограничивается этим подграфом.
Если же модуль является общим для всех таргетов и изменяется его универсальная логика, пересобираются все зависимые ветки. Однако даже в этом случае пересчёт остаётся локализованным относительно общего графа, без полного пересоздания сборки.
Механизм выборочной сборки изменённых таргетов особенно критичен для:
Снижение объёма пересборки напрямую уменьшает время обратной связи и повышает эффективность разработки, особенно при больших графах зависимостей и сложной структуре таргетов.