Миграция с ESLint 7 на 8

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

Ключевые изменения:

  • требуется Node.js >= 12.22.0
  • прекращена поддержка Node.js 10 и 13
  • частично ограничена совместимость с очень старыми версиями npm/yarn

В проектах с CI/CD необходимо синхронизировать версии Node.js во всех окружениях: локальная разработка, сборка, тестирование, деплой.


Обновление зависимостей проекта

Обновление ESLint до восьмой версии выполняется через замену пакета:

npm install eslint@8 --save-dev

или

yarn add eslint@8 -D

После обновления требуется проверить все связанные пакеты:

  • eslint-plugin-*
  • eslint-config-*
  • парсеры (babel-eslint, @typescript-eslint/parser)
  • инструменты интеграции (webpack, gulp, jest пресеты)

Многие плагины ESLint 7 продолжают работать, однако часть из них требует обновления из-за изменений peerDependencies.


Удаление CLIEngine и переход на новый API

Одним из ключевых архитектурных изменений становится окончательное удаление CLIEngine.

Что изменилось

  • CLIEngine полностью удалён из API
  • единственным поддерживаемым программным интерфейсом остаётся класс ESLint
  • плагины и инструменты, использующие CLIEngine, перестают работать без адаптации

Было (ESLint 7)

const { CLIEngine } = require("eslint");

const cli = new CLIEngine({
  fix: true
});

const report = cli.executeOnFiles(["src"]);

Стало (ESLint 8)

const { ESLint } = require("eslint");

const eslint = new ESLint({ fix: true });

const results = await eslint.lintFiles(["src"]);
await ESLint.outputFixes(results);

Важные последствия

  • переход на асинхронную модель выполнения
  • необходимость использования async/await или промисов
  • переработка кастомных инструментов анализа кода

Изменения конфигурационной системы

ESLint 8 продолжает использовать eslintrc как стандартную модель конфигурации, однако усиливается консистентность поведения.

Основные особенности

  • строгая обработка конфликтов конфигураций
  • более предсказуемое объединение extends
  • улучшенная работа с overrides

Пример структуры:

{
  "env": {
    "browser": true,
    "node": true
  },
  "extends": ["eslint:recommended"],
  "rules": {
    "no-unused-vars": "warn"
  }
}

Поведение overrides

Изменена приоритетность применения правил в сложных конфигурациях:

{
  "overrides": [
    {
      "files": ["*.test.js"],
      "rules": {
        "no-unused-expressions": "off"
      }
    }
  ]
}

Теперь порядок применения overrides становится более детерминированным, особенно при глубокой вложенности конфигов.


Совместимость плагинов и парсеров

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

Типичные проблемы

  • устаревшие версии eslint-plugin-*
  • несовместимость @typescript-eslint старых версий
  • использование deprecated parser API

Рекомендуемые обновления

  • @typescript-eslint/parser версии 5+
  • @typescript-eslint/eslint-plugin версии 5+
  • обновление babel-парсеров до актуальных релизов

Пример обновления TypeScript-стека

npm install @typescript-eslint/parser@latest @typescript-eslint/eslint-plugin@latest -D

Изменения поведения правил

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

Основные изменения

  • улучшена точность анализа no-constant-condition
  • корректировки в no-loss-of-precision при работе с большими числами
  • уточнение поведения no-unused-vars в сложных деструктуризациях

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

const { a, b } = obj;

// ранее могли возникать ложные предупреждения
// теперь анализ учитывает контекст использования

Изменения CLI-инструмента

CLI-интерфейс ESLint 8 подвергся оптимизации и частичной переработке.

Новые особенности

  • улучшенная производительность при больших проектах
  • более строгая обработка флагов
  • унификация поведения --fix

Пример использования

npx eslint "src/**/*.{js,ts}" --fix

Важные изменения

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

Асинхронная модель выполнения

Переход от синхронного CLIEngine к асинхронному API ESLint приводит к необходимости пересмотра архитектуры инструментов.

Основные последствия

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

Пример адаптации

async function runLint() {
  const eslint = new ESLint({ fix: true });

  const results = await eslint.lintFiles(["src"]);
  await ESLint.outputFixes(results);
}

Типичные проблемы миграции

Конфликты версий плагинов

Ситуации, при которых ESLint 8 установлен, но плагины остаются на ESLint 7 API, приводят к ошибкам загрузки:

  • ESLint version mismatch
  • Cannot read property 'defineRule'
  • context.parserServices undefined

Ошибки конфигурации

При неправильной настройке extends или overrides возможны:

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

Проблемы с TypeScript

Наиболее частые ошибки:

  • несовместимость parserServices
  • устаревшие версии typescript-estree
  • неправильная настройка project в parserOptions

Стратегия перехода между версиями

Процесс миграции обычно разбивается на несколько этапов.

Анализ текущей конфигурации

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

Обновление ядра ESLint

  • установка ESLint 8
  • обновление Node.js
  • проверка запуска базовой команды lint

Обновление экосистемы

  • синхронизация версий eslint-plugin-*
  • обновление TypeScript парсеров
  • адаптация кастомных конфигов

Рефакторинг интеграций

  • перевод кастомных скриптов на ESLint class API
  • обновление CI/CD пайплайнов
  • корректировка pre-commit хуков

Изменения в производительности

ESLint 8 демонстрирует улучшения производительности на крупных кодовых базах.

Основные факторы:

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

Особенно заметен прирост при работе с монорепозиториями и TypeScript-проектами.


Обработка кэширования

Кэширование стало более стабильным и предсказуемым.

Особенности

  • улучшена устойчивость к изменению конфигураций
  • уменьшено количество ложных cache miss
  • ускорена повторная проверка файлов
npx eslint src --cache

Итоговые технические последствия миграции

Переход на ESLint 8 приводит к структурным изменениям в архитектуре линтинга:

  • удаление синхронного API CLIEngine
  • переход на асинхронный ESLint class API
  • повышение требований к Node.js
  • необходимость обновления экосистемы плагинов
  • улучшение производительности и стабильности анализа кода