Механизм кеширования

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

Общая модель кеширования

Кеш ESLint строится вокруг сопоставления входных данных анализа и результатов проверки. Входными данными выступают:

  • содержимое файла;
  • конфигурация линтера (конфиги, наследование, overrides);
  • список подключённых плагинов и правил;
  • параметры CLI, влияющие на семантику проверки.

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

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

Физическое представление кеша

По умолчанию ESLint использует файл .eslintcache, размещаемый в корне проекта. Этот файл представляет собой сериализованную структуру данных, содержащую:

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

Формат кеша бинарно-ориентированный (внутренний формат ESLint), оптимизированный для быстрого чтения и записи, а не для ручного редактирования.

Активация кеширования

Кеширование включается через CLI-флаг:

eslint . --cache

При включении ESLint начинает сохранять результаты анализа и повторно использовать их при следующих запусках.

Дополнительно может задаваться путь к файлу кеша:

eslint . --cache --cache-location ./tmp/eslint-cache

Это позволяет изолировать кеш между окружениями, ветками или CI-джобами.

Алгоритм определения актуальности кеша

При повторном запуске ESLint выполняет проверку валидности кеша на уровне каждого файла. Основные этапы:

1. Вычисление хеша содержимого файла

Для каждого файла формируется хеш на основе его текущего содержимого. Любое изменение — даже минимальное (например, пробел или перенос строки) — приводит к изменению хеша.

2. Сопоставление с сохранённой записью

Если файл присутствует в кеше, ESLint сравнивает:

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

Несовпадение любого элемента приводит к инвалидированию кеша для конкретного файла.

3. Проверка конфигурационного контекста

Конфигурация ESLint влияет на результат линтинга сильнее, чем содержимое файла. Изменения в:

  • .eslintrc.*;
  • eslint.config.js (flat config);
  • настройках CLI;
  • подключённых плагинах;

приводят к частичной или полной очистке кеша.

Стратегии кеширования

ESLint поддерживает различные стратегии формирования кеш-ключа, определяющие уровень точности сравнения.

metadata стратегия

Стратегия по умолчанию. Использует метаданные файловой системы:

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

Данная стратегия обеспечивает высокую скорость, но может быть менее точной в окружениях, где метаданные файловой системы ненадёжны (например, при синхронизации через сетевые диски).

content стратегия

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

eslint . --cache --cache-strategy content

Данный подход снижает риск ложных попаданий кеша, но увеличивает вычислительные затраты на его формирование.

Инвалидация кеша

Инвалидация кеша происходит при следующих условиях:

Изменение исходного кода

Любое изменение содержимого файла делает кеш-элемент недействительным.

Изменение конфигурации ESLint

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

Изменение версии ESLint или плагинов

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

Изменение параметров CLI

Флаги, влияющие на процесс анализа (--rule, --env, --parser, --ext), участвуют в формировании ключа кеша.

Поведение в монорепозиториях

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

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

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

Рекомендуемая практика — разделение кеша по пакетам:

eslint packages/* --cache --cache-location packages/a/.eslintcache

Это снижает вероятность конфликтов между различными конфигурациями.

Кеширование и плагинная архитектура

Плагины ESLint влияют на кеш не только через правила, но и через собственные процессоры и парсеры.

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

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

Таким образом, кеш ESLint чувствителен не только к исходному файлу, но и к цепочке его преобразований.

Оптимизация кеша в CI/CD

В CI-средах кеш используется для ускорения повторных запусков линтера между сборками.

Типовые подходы:

сохранение кеша между джобами

Кеш файл сохраняется как артефакт и восстанавливается в следующем запуске:

eslint . --cache --cache-location .cache/eslint

ограничение области кеширования

В CI часто линтируются только изменённые файлы, что усиливает эффективность кеша:

eslint . --cache --cache-strategy metadata

проблемы параллельного выполнения

При параллельных джобах кеш может перезаписываться. Для предотвращения используются:

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

Производительность и стоимость кеширования

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

  • вычисление хешей;
  • чтение/запись кеш-файла;
  • проверка валидности записей.

Эффект кеша становится заметен при большом количестве файлов (сотни и тысячи). В небольших проектах выигрыш может быть минимальным или отсутствовать.

Ограничения механизма кеширования

Несмотря на оптимизацию, кеш ESLint имеет ряд ограничений:

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

Также кеш не учитывает семантические изменения, если они не отражены в входных данных (например, внешние зависимости, используемые в кастомных правилах).

Сценарии, в которых кеш отключается

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

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

В таких сценариях ESLint выполняет полноценный анализ без повторного использования предыдущих результатов.

Влияние flat config на кеширование

Новая система конфигурации ESLint (flat config) усиливает детерминированность кеша. Конфигурация становится более явной, что снижает количество скрытых зависимостей.

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

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

Однако динамические конструкции в конфиге (условные экспорты, вычисляемые правила) могут увеличивать нестабильность кеша.

Итоговая модель поведения кеша

Кеш ESLint функционирует как детерминированное отображение:

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

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