6 февраля 2026 вышел ESLint 10.0.0, и для многих команд это не релиз из категории “обновим потом”. В v10 не просто чуть поменяли правила. Тут добили старый формат конфигурации, отключили часть привычных CLI-флагов и сделали flat config единственной нормальной точкой входа.
Из-за этого главный вопрос звучит не как “какие новые правила появились в ESLint 10”. Главный вопрос звучит так: можно ли вашей кодовой базе обновляться прямо сейчас, и если да, то в каком порядке делать миграцию, чтобы не устроить неделю ложных тревог в CI, редакторе и ревью.
Эта статья про практический маршрут. Ниже разберем, кому уже пора на v10, кому лучше пока остаться на v9, что именно ломает старая схема настройки и как провести переход так, чтобы это был один предсказуемый инфраструктурный PR, а не бессмысленная война за кодстайл.
Обновлено 1 апреля 2026: статья переписана. Добавлены правило выбора, новый сценарий миграции и более практическая структура.
- Стоит ли обновляться на ESLint 10 прямо сейчас
- Что именно в v10 ломает старую конфигурацию
- Порядок миграции без лишнего шума
- Минимальный eslint.config.js, от которого можно стартовать
- Где переход ломается чаще всего
- Когда лучше остаться на ESLint 9
- Где читать первоисточник
- Итог
Стоит ли обновляться на ESLint 10 прямо сейчас
Есть два очень разных сценария.
Первый: проект уже живет на eslint.config.js, Node у команды и CI не ниже 20.19.0, а плагины и переиспользуемые конфиги поддерживаются без костылей. В таком случае переход на ESLint 10 обычно выглядит как нормальное техническое обновление. Да, новые ошибки могут появиться, но это уже управляемая история.
Второй: проект все еще на .eslintrc*, часть людей запускает линтер на старом Node, а в CI и редакторе живут разные способы конфигурации. В этом состоянии апгрейд почти никогда не является “обновлением линтера”. Это миграция всего слоя линтинга.
Обновляться прямо сейчас разумно, если:
- у вас уже есть
flat configили вы готовы мигрировать на него в этом же PR; - локально и в CI используется Node
20.19.0+; - у проекта нет критичного старого пресета, который полностью блокирует
flat config; - у команды есть ресурс довести переход до зелёного состояния, а не бросить на полпути.
Лучше пока не торопиться, если:
- проект сидит на Node
18или раннем Node20; - у вас большой монорепозиторий на старых переиспользуемых конфигах;
- редакторная интеграция и CI живут на разных версиях и флагах;
- сейчас нет времени нормально отделить PR с миграцией от последующей чистки правил.
Если сжать всё до одного правила, оно такое: ESLint 10 стоит ставить не тогда, когда “релиз уже вышел”, а тогда, когда команда готова одновременно закрыть runtime, конфиг и скрипты.
Что именно в v10 ломает старую конфигурацию
Ниже не полный changelog релиза, а именно то, что чаще всего бьет по обычному фронтенд-проекту.
- Node.js ниже
20.19.0, а также ветки21.xи23.x, больше не поддерживаются. - Старый конфиг
.eslintrc*больше не поддерживается вообще. Нуженeslint.config.js. .eslintignoreбольше не читается автоматически.- CLI-флаги
--env,--ignore-path,--no-eslintrc,--resolve-plugins-relative-toи--rulesdirбольше не работают сflat config. /* eslint-env */комментарии теперь репортятся как ошибки.eslint:recommendedполучил новые правила:no-unassigned-vars,no-useless-assignment,preserve-caught-error.- ESLint начал корректно учитывать JSX references, поэтому часть старых React-обходных путей больше не нужна.
- Новый алгоритм поиска
eslint.config.*стал дефолтным, а старый флаг больше не нужен.
Это важный момент: для многих команд основная боль после апгрейда приходит не из приложения и не из компонентов, а из того, что старый способ настройки ESLint в v10 просто перестал существовать.
Порядок миграции без лишнего шума
Самая частая ошибка здесь одна и та же: обновить всё сразу, получить поток репортов и начать чинить их без разбора. Намного лучше работает другой порядок.
1. Фиксация текущего состояния
Перед апгрейдом полезно убедиться, что текущий линтер уже зеленый. Если проект красный и до обновления, ESLint 10 ничего не прояснит. Он просто смешает старый техдолг с новыми ломающими изменениями.
Практически это значит одно: апгрейд лучше делать отдельной веткой и отдельным PR, без параллельной реформы кодстайла.
2. Runtime и редактор — до изменений в правилах
Перед любыми изменениями в конфиге стоит убедиться, какой Node реально запускает ESLint локально, в CI и в редакторе.
node -v
npx eslint -v
npm ls eslintЕсли проект сидит на Node 18 или раннем Node 20, “частичный” апгрейд только добавит шум. В таком состоянии разумнее оставаться на ESLint 9, пока runtime не будет поднят хотя бы до 20.19.0.
3. Если в проекте еще .eslintrc*, сначала миграция, потом обновление
Официальный стартовый маршрут выглядит так:
npx @eslint/migrate-config .eslintrc.json
npm i -D eslint@10 @eslint/js globalsЕсли конфиг был не JSON, а .eslintrc.js с функциями, условиями или переменными, утилита миграции даст только стартовую заготовку. Это нормально. Ее задача не заменить архитектурное решение команды, а быстро перевести старый формат в рабочую базу.
Если проект зависит от переиспользуемого конфига, который еще не умеет работать с flat config, обычно нужен переходный мост:
npm i -D @eslint/eslintrc @eslint/compat@eslint/eslintrc нужен для FlatCompat, а @eslint/compat полезен, если проекту нужно подтянуть .gitignore через includeIgnoreFile() или временно смягчить несовместимости экосистемы.
4. Перенос старых точек настройки в новые места
После апгрейда люди часто чинят не то, что сломалось, а то, что сами забыли перенести из старой системы. Удобнее сразу смотреть на замену один-к-одному:
Было до v10 |
Что делать в v10 |
|---|---|
.eslintrc* |
перейти на eslint.config.js |
.eslintignore или --ignore-path |
использовать ignores или includeIgnoreFile() |
--env browser,node |
переносить globals в languageOptions.globals |
noInlineConfig, reportUnusedDisableDirectives в старом конфиге |
переносить в linterOptions |
extends: ["eslint:recommended"] |
импортировать @eslint/js и брать js.configs.recommended |
/* eslint-env node */ |
удалить комментарий и объявить globals в конфиге |
старый пресет без flat config |
временно подключать через FlatCompat |
Если не сделать этот перенос сразу, дальше разбирать придется не ошибки кода, а мусор от поломанной конфигурации.
5. Обновление скриптов в package.json и CI
Конфиг может быть уже новым, а команда всё равно может видеть хаос, потому что скрипты запускают ESLint по старым правилам.
То, что нужно убрать из команд:
--env--ignore-path--no-eslintrc--resolve-plugins-relative-to--rulesdir--flag v10_config_lookup_from_file
Если проект раньше полагался на старый поиск от текущей директории, в v10 конфиг нужно задавать явно:
eslint . --config ./eslint.config.jsЭто же место, где стоит проверить переменные окружения и старые CI-шаблоны. Особенно если в пайплайне кто-то когда-то добавил ESLINT_FLAGS и потом все забыли, зачем.
6. Разбор новых сообщений линтера
После этого уже есть смысл запускать линтер и раскладывать результат по типам:
- реальные новые ошибки из
eslint:recommended; - шум от старых React/JSX-обходных решений;
- старые
eslint-disable, которые раньше никто не трогал; - правила, которые команда больше не хочет поддерживать;
- исторический мусор, который просто случайно совпал по времени с апгрейдом.
Самое полезное правило на этом этапе: PR с миграцией и идеологическая чистка конфигурации не должны смешиваться. Сначала апгрейд должен стать предсказуемым. Уже потом можно отдельно спорить о стилистических правилах.
Минимальный eslint.config.js, от которого можно стартовать
Ниже минимальный eslint.config.js, от которого можно оттолкнуться в обычном JS/JSX-проекте. Он не решает весь стек целиком, но показывает, куда теперь переезжают базовые настройки.
import { defineConfig } from "eslint/config";
import js from "@eslint/js";
import globals from "globals";
export default defineConfig([
{
ignores: ["dist/**", "coverage/**", "**/.*"],
},
js.configs.recommended,
{
files: ["**/*.{js,mjs,cjs,jsx}"],
languageOptions: {
globals: {
...globals.browser,
...globals.node,
},
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
linterOptions: {
reportUnusedDisableDirectives: "warn",
},
},
]);Дальше на этот базовый слой добавляются официальные конфиги для конкретного стека: TypeScript, React, Testing Library, правила для импортов и так далее. Полезно именно то, что ось теперь одна: eslint.config.js, а не набор старых файлов, комментариев и CLI-обходных путей.
Если в проекте есть старый пресет, который еще не умеет работать с flat config, переписывать его целиком в один вечер нерационально. На переходном этапе его можно подключить через FlatCompat, пережить апгрейд ядра, а уже потом вынести совместимость отдельной задачей.
Где переход ломается чаще всего
React и JSX
Одна из самых полезных практических изменений в v10 в том, что ESLint теперь нормально учитывает JSX references. Для React-проекта это означает, что часть старых обходных правил может стать просто ненужной.
Если какое-то правило или плагин раньше был нужен только для того, чтобы <Card /> не считался “неиспользованным импортом”, после апгрейда его стоит перепроверить. Очень часто шум идет именно отсюда.
TypeScript и переиспользуемые конфиги
Если конфиг написан на TypeScript, важно не забыть про jiti: это загрузчик, который позволяет Node.js и инструментам вокруг него читать TypeScript- и ESM-файлы без отдельной предварительной компиляции. Для ESLint 10 нужна версия jiti не ниже 2.2.0.
Вторая типичная проблема здесь не в TypeScript как таковом, а в старых переиспользуемых конфигах. Если они еще не поддерживают flat config, не превращай апгрейд в переписывание всей внутренней платформы. Подключи совместимость, стабилизируй переход и только потом разбирайся с архитектурной чисткой.
CI и редактор
После миграции конфиг может быть правильным, а команда всё равно может видеть разные результаты локально и в пайплайне.
Что здесь проверить:
- CI действительно запускает ту же команду, что и локально;
- в CI нет старых переменных вроде
ESLINT_FLAGS=v10_config_lookup_from_file; - VS Code extension не слишком старый;
- если цвета вывода внезапно поменялись, стоит проверить
NO_COLORиNODE_DISABLE_COLORS.
Отдельно про редактор: в официальной документации ESLint указано, что поддержка нового flat config для vscode-eslint была добавлена в 3.0.10. Если в команде кто-то сидит на более старом расширении, он может видеть другой linting, чем тот, что реально запускается в CI.
Старые eslint-env и исторические исключения
Если в кодовой базе остались строки вроде:
/* eslint-env node */их нужно убирать. В v10 такой комментарий не “помогает конфигу”, а ломает lint run.
То же относится к старым eslint-disable, забытым пресетам и отключениям, смысл которых уже никто не помнит. Это не повод вычищать все сразу, но очень хороший сигнал, что после миграции нужен отдельный PR на чистку.
Когда лучше остаться на ESLint 9
Иногда самая взрослая техническая стратегия здесь не “обновиться быстрее”, а честно отложить переход.
Остаться на ESLint 9 еще на один цикл разумно, если:
- команда не может быстро перейти на Node
20.19.0+; - проект сильно завязан на старый
.eslintrc*-стек и непонятные переиспользуемые конфиги; - нет ресурса закончить миграцию до зеленого CI;
- апгрейд почти наверняка сольется с большой перестройкой правил, что уничтожит пользу от отдельного PR.
В этом нет ничего постыдного. Плох не “поздний апгрейд”, а апгрейд, который команда бросила в полуразобранном состоянии и после которого линтеру больше никто не доверяет.
Где читать первоисточник
Для первоисточника полезны три ссылки:
Если конкретно разваливается переход с .eslintrc на eslint.config.js, первым источником должен быть гайд по миграции. Если нужен список ломающих изменений, полезно открыть migrate-to-v10 и release notes вместе.
Итог
У ESLint 10 главный смысл не в том, что он “строже” или “умнее”. Главный смысл в том, что эпоха старого конфига закончилась окончательно. Поэтому и апгрейд надо воспринимать не как обновление одной зависимости, а как аккуратную миграцию слоя линтинга.
Самый практичный путь здесь один: отдельный PR, сначала runtime, потом eslint.config.js, потом скрипты и CI, и только потом разбор новых сообщений линтера. Если проект готов к flat config и Node 20.19.0+, это обычно нормальный рабочий апгрейд. Если не готов, лучше честно остаться на ESLint 9, чем превратить линтер в источник фонового шума еще на полгода.