Кэш в Parcel представляет собой фундаментальный слой ускорения сборки, основанный на принципе повторного использования результатов предыдущих трансформаций. В основе лежит файловый кэш на диске и граф зависимостей, который позволяет избегать повторной обработки неизменённых модулей.
Parcel сохраняет промежуточные результаты:
Ключевая идея заключается в том, что каждый модуль получает детерминированный идентификатор состояния, зависящий от содержимого и окружения трансформации.
Основной механизм инвалидации кэша в Parcel основан на content hashing — вычислении хэша от содержимого файла и его зависимостей.
Хэш формируется из нескольких факторов:
Любое изменение одного из этих элементов приводит к изменению хэша, что автоматически делает кэш устаревшим.
Таким образом реализуется принцип:
изменение входных данных → изменение хэша → новая версия артефакта
Parcel строит граф модулей, в котором каждый узел представляет файл или ресурс, а ребра отражают зависимости.
Инвалидация происходит не только на уровне одного файла, но и каскадно:
При этом Parcel избегает полного пересборки проекта за счёт изолированного пересчёта подграфов.
Особенность системы заключается в том, что пересборка ограничивается минимально затронутой областью графа.
Parcel использует директорию .parcel-cache для хранения
промежуточных данных.
Внутри кэша сохраняются:
Кэш организован как контент-адресуемое хранилище. Это означает, что ключом является хэш содержимого, а не путь к файлу.
Такой подход обеспечивает:
При изменении файла Parcel выполняет цепочку проверок:
Если изменения отсутствуют, модуль берётся из кэша без повторной обработки.
Особенно эффективно это проявляется в монорепозиториях, где множество пакетов могут ссылаться на одни и те же зависимости.
Изменения конфигурационных файлов приводят к более широкой инвалидации.
К таким файлам относятся:
package.json.babelrctsconfig.jsonParcel включает конфигурацию в вычисление хэша модулей. Поэтому изменение конфигурации может привести к пересчёту большого числа узлов графа, даже при неизменном исходном коде.
Изменение пакетов в node_modules вызывает пересборку
зависимых модулей.
Parcel отслеживает:
package-lock.json, yarn.lock,
pnpm-lock.yaml)Любое изменение этих данных приводит к пересчёту соответствующих кэш-ключей.
В режиме разработки используется Hot Module Replacement (HMR), который тесно связан с системой инвалидации кэша.
При изменении файла:
Parcel стремится минимизировать перезагрузку страницы, заменяя только изменённые участки кода.
Инвалидация здесь работает на уровне модулей, а не всего бандла.
Parcel использует систему плагинов и трансформеров, которые могут влиять на результат сборки.
Если изменяется:
то пересчитываются все модули, которые проходят через данный трансформер.
Это связано с тем, что результат трансформации считается недетерминированным относительно старой версии плагина.
Parcel использует несколько стратегий оптимизации кэша:
1. Контент-адресуемый кэш Одинаковые входные данные всегда дают одинаковый результат.
2. Инкрементальная сборка Обновляются только затронутые узлы графа.
3. Параллельное выполнение трансформаций Независимые модули обрабатываются одновременно.
4. Ленивое вычисление Некоторые оптимизации выполняются только при необходимости.
В некоторых ситуациях кэш может стать неконсистентным, например:
.parcel-cacheВ таких случаях применяется полная инвалидация:
.parcel-cacheПолная очистка приводит к потере всех промежуточных результатов, но восстанавливает корректность сборки.
Механизм кэширования и инвалидации может сталкиваться с рядом сложностей:
1. Непредсказуемые плагины Если плагин использует внешние данные без учёта в хэше, кэш становится некорректным.
2. Динамические импорты Позднее вычисление зависимостей усложняет построение стабильного графа.
3. Побочные эффекты трансформаций Если трансформер зависит от состояния окружения, кэширование теряет детерминизм.
4. Файлы вне графа зависимостей Некоторые ресурсы могут не отслеживаться напрямую, что требует ручной инвалидации.
Для корректной работы системы кэширования важен детерминизм всех этапов сборки:
Parcel проектирует систему вокруг предположения, что сборка должна быть воспроизводимой при любых повторных запусках при неизменном входе.