Производительность сборки и кэш

Parcel использует многоуровневую систему кэширования, ориентированную на сокращение времени повторных сборок и минимизацию повторной обработки неизменённых модулей. Основная идея заключается в сохранении результатов трансформаций, анализа зависимостей и упаковки в промежуточном кэше, который используется при последующих запусках.

Кэш хранится на уровне файловой системы и включает:

  • результаты трансформации исходного кода;
  • граф зависимостей модулей;
  • результаты минификации и оптимизации;
  • метаданные о файлах и их хешах.

Кэш является персистентным, что означает сохранение между запусками процесса сборки.

Принципы работы инкрементальной сборки

Parcel строит граф зависимостей один раз, после чего работает только с изменёнными узлами графа. При изменении файла пересчитывается только его подграф зависимостей, а не весь проект.

Ключевым механизмом является отслеживание хешей содержимого:

  • каждый модуль получает content hash;
  • изменения фиксируются через сравнение хешей;
  • неизменённые узлы графа пропускаются в пайплайне трансформаций.

Это позволяет резко уменьшить время rebuild при сохранении корректности результата.

Хеширование и стратегия invalidation

В основе системы лежит хеш содержимого, а не времени изменения файла. Такой подход снижает вероятность ложных инвалидаций.

Хеш вычисляется на основе:

  • исходного содержимого файла;
  • зависимостей модуля;
  • конфигурации трансформеров;
  • переменных окружения сборки.

При изменении любого из этих факторов происходит инвалидация кэша конкретного узла графа.

Особое значение имеет детерминированность: одинаковый вход всегда должен давать одинаковый хеш, что критично для воспроизводимости сборки.

Файловый кэш и структура хранения

Parcel сохраняет кэш в директории .parcel-cache. Внутри используется структурированное распределение данных:

  • индексы модулей;
  • сериализованные AST;
  • результаты трансформаций (Babel, TypeScript, PostCSS и др.);
  • сгенерированные бандлы;
  • служебные метаданные.

Файлы кэша оптимизированы под быстрый доступ и частичное чтение. Это снижает I/O нагрузку при инкрементальных сборках.

Кэширование трансформаций

Каждый трансформер в Parcel (например, Babel или Sass) работает как чистая функция от входного модуля и конфигурации.

Система кэширует:

  • входной код;
  • конфигурацию плагинов;
  • версию трансформера;
  • результат AST-преобразований.

При совпадении всех параметров трансформация не выполняется повторно, а результат берётся из кэша.

Параллелизм и использование многопоточности

Parcel активно использует многопоточную обработку через worker threads. Это позволяет распределять нагрузку между ядрами процессора.

Параллельно выполняются:

  • трансформации модулей;
  • минификация;
  • генерация sourcemap;
  • оптимизация зависимостей.

Каждый воркер работает с изолированным состоянием, а кэш синхронизируется через общий файловый слой.

Оптимизация графа зависимостей

Граф зависимостей в Parcel является центральной структурой, определяющей производительность сборки.

Оптимизации включают:

  • ленивое вычисление узлов графа;
  • удаление недостижимых модулей (tree shaking на уровне графа);
  • объединение смежных узлов с одинаковыми трансформациями;
  • переиспользование подграфов между сборками.

Чем стабильнее структура проекта, тем эффективнее работает повторное использование узлов графа.

Cold start и warm rebuild

Различие между холодной и тёплой сборкой существенно влияет на производительность.

Cold start:

  • отсутствует кэш;
  • выполняется полный анализ графа;
  • все трансформации запускаются заново;
  • время сборки максимальное.

Warm rebuild:

  • кэш уже существует;
  • анализируется только изменённый подграф;
  • большинство трансформаций пропускается;
  • время сборки сокращается кратно.

Кэширование в dev-режиме

В режиме разработки Parcel оптимизирует сборку под частые изменения файлов.

Используются механизмы:

  • мгновенное обновление изменённых модулей;
  • частичная пересборка бандлов;
  • сохранение состояния графа в памяти между изменениями;
  • приоритизация быстрого отклика над полной оптимизацией.

В результате изменения кода отражаются в сборке почти мгновенно, особенно в проектах средней сложности.

Работа с node_modules и внешними зависимостями

Зависимости из node_modules обрабатываются отдельно и кэшируются агрессивнее, чем пользовательский код.

Особенности:

  • анализируются один раз при установке зависимостей;
  • повторно не пересобираются без изменения версии;
  • их AST и трансформации сохраняются в глобальном кэше;
  • минимизируется влияние на инкрементальные сборки.

Это значительно снижает стоимость больших зависимостей в проекте.

Стабильность кэша и проблемы инвалидации

Одной из ключевых задач системы является предотвращение избыточной инвалидации кэша.

Проблемные случаи:

  • нестабильные плагины, возвращающие разные результаты при одинаковом входе;
  • использование случайных значений в конфигурации сборки;
  • некорректные версии зависимостей;
  • изменения порядка импортов, влияющие на граф.

Parcel решает эти проблемы через строгую детерминированность пайплайна и контроль входных параметров трансформаций.

Метрики производительности кэш-системы

Эффективность кэширования можно оценивать через несколько ключевых показателей:

  • доля cache hit rate в трансформациях;
  • время восстановления графа зависимостей;
  • количество пересобранных модулей на изменение;
  • latency dev-сборки;
  • I/O нагрузка на файловую систему.

Высокий cache hit rate напрямую коррелирует с сокращением времени сборки.

Минификация и постобработка в контексте кэша

Минификация также включена в систему кэширования. Результаты сохраняются отдельно для разных режимов сборки.

Кэшируются:

  • AST после трансформаций;
  • результаты Terser или аналогичных инструментов;
  • оптимизированные строки и структуры кода;
  • source maps.

Это позволяет избегать повторной дорогостоящей обработки финального бандла при небольших изменениях исходников.

Влияние конфигурации на кэш

Любое изменение конфигурации сборщика приводит к пересчёту соответствующих частей кэша.

К конфигурационным факторам относятся:

  • .parcelrc;
  • версии плагинов;
  • настройки targets (browser/node);
  • параметры оптимизации;
  • env-переменные сборки.

Parcel учитывает конфигурацию как часть ключа кэша, обеспечивая корректность пересборки при изменениях окружения.