ESLint — линтер для JavaScript
ESLint находит в коде ошибки, потенциальные баги и нарушения стиля до того, как они попадут на прод. Это статический анализатор: он не запускает код, а проверяет его по правилам, многие из которых можно исправить одной командой.
1. Что такое линтер и зачем он нужен
Линтер (linter) — программа, которая анализирует исходный код и находит проблемные места. ESLint — стандарт для JavaScript и TypeScript. Что он умеет:
- ловить неиспользуемые переменные и недостижимый код;
- предупреждать небезопасные конструкции (например, сравнение через
==вместо===); - единый стиль кода для всей команды;
- автоисправление большинства найденного.
2. Установка
ESLint ставится как npm-пакет. Работай в папке проекта:
npm init -y
npm install --save-dev eslint
npx eslint --init # интерактивная настройкаУбедись, что установка прошла:
npx eslint app.js
# пустой вывод = ошибок нет (или они ниже)3. Flat config: eslint.config.js
С версии ESLint 9 используется flat config — файл eslint.config.js вместо старого .eslintrc. Минимальный конфиг:
// eslint.config.js
export default [
{
files: ["**/*.js"],
rules: {
"no-unused-vars": "warn",
"semi": ["error", "always"]
}
}
]Ключевые поля:
files— какие файлы проверять (glob-паттерны);ignores— что игнорировать;languageOptions— версия экмаскрипта, источники (browser/node), parserOptions;rules— отключение/настройка правил;plugins— дополнительные наборы правил.
env и extends. В flat config их заменили languageOptions и объекты с configs.4. Уровни правил
Каждое правило принимает одно из значений:
| Уровень | Значение | Что происходит |
|---|---|---|
| off | 0 | правило выключено |
| warn | 1 | жёлтое предупреждение, код работает |
| error | 2 | красная ошибка, «нельзя коммитить» |
rules: {
"no-undef": "error", // запрет необъявленных переменных
"quotes": ["error", "single"], // одинарные кавычки
"max-len": ["warn", { "code": 100 }] // строка до 100 символов
}5. Готовые наборы: recommended и extends
Вместо написания ста правил с нуля подключают готовые наборы из объектов конфигурации линтера или отдельных пакетов:
// eslint.config.js с рекомендуемым набором
import eslint from "@eslint/js";
export default [
eslint.configs.recommended,
{
files: ["**/*.js"],
rules: {
"no-unused-vars": "warn"
}
}
]eslint.configs.recommended включает десятки проверенных правил: no-undef, no-unreachable, eqeqeq и другие. Большинство проектов начинают именно с него.
6. Автоисправление --fix
Многие правила исправляются автоматически (fixable). Команда:
npx eslint app.js --fixESLint переформатирует кавычки, точки с запятой, лишние пробелы и прочее. Например, правило quotes само заменит двойные кавычки на одинарные, если так настроено.
7. ESLint в VS Code
Установи расширение ESLint (от Microsoft). После этого ошибки подсвечиваются прямо в редакторе, а при включённой опции исправляются при сохранении:
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
}Настройки VS Code уже знают путь ESLint из проекта; если используются нескольких окружений — укажи явно eslint.nodePath.
8. Игнорирование файлов
Не все файлы нужно проверять: сборки, сторонние библиотеки, сгенерированный код. В flat config игнорирование — в поле ignores:
export default [
{
ignores: ["dist/**", "node_modules/**", "build/*.js", ".env"]
},
eslint.configs.recommended
].eslintignore игнорируется — переноси всё в ignores конфига.9. Плагины: React, Vue, TypeScript
Для фреймворков и TS подключаются отдельные плагины:
| Пакет | Для чего |
|---|---|
eslint-plugin-react | правила для React: hooks, prop-types |
eslint-plugin-vue | правила для Vue SFC: template, script |
typescript-eslint | правила для TypeScript вместо расширения @typescript-eslint/* |
eslint-plugin-import | проверка import/export |
eslint-config-prettier | отключает правила, конфликтующие с Prettier |
npm install --save-dev typescript-eslint
// eslint.config.js
import tseslint from "typescript-eslint";
export default [
...tseslint.configs.recommended,
{ files: ["**/*.ts"] }
].configs[recommended] — проверь документацию плагина и разверни его через ....10. ESLint в CI и git-hooks
Чтобы плохой код не попадал в основную ветку, линтер запускают автоматически: в CI на каждый push или pull request и локально перед коммитом через git hook. В GitHub Actions это шаг workflow:
// .github/workflows/ci.yml
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci
- run: npx eslint . --max-warnings 0Флаг --max-warnings 0 превращает предупреждения в ошибки: даже «жёлтые» проблемы остановят сборку и заставят их исправить, а не отложить.
lint-staged: он прогоняет линтер только по изменённым файлам, и проверка занимает секунды, а не минуты.11. Связка ESLint и Prettier
ESLint отвечает за ошибки, но про форматирование спорить не умеет — для этого есть Prettier. Чтобы два инструмента не ругались друг с другом, подключают пакет eslint-config-prettier, отключающий конфликтующие правила:
npm install --save-dev prettier eslint-config-prettier
// eslint.config.js
import prettier from "eslint-config-prettier";
export default [
eslint.configs.recommended,
prettier
]Разделение зон ответственности:
- ESLint — сравнения, неиспользуемые переменные,
no-undef, потенциальные баги; - Prettier — кавычки, переносы строк, отступы, единый стиль форматирования.
12. Отчёты и точечные отключения
Для CI полезно формировать отчёты в парсируемых форматах — например JSON или JUnit, по которым строят графики и ссылки в комментариях PR:
npx eslint . -f json -o eslint-report.json
npx eslint . -f junit -o junit.xmlВ коде отдельные строки или файлы исключают точечно:
// отключить правило на следующую строку
// eslint-disable-next-line no-console
console.log("отладка");
// отключить для файла целиком
/* eslint-disable no-alert */eslint-disable-next-line — сигнал пересмотреть правило или провести рефакторинг.13. Типовая настройка и чек-лист
Минимальный рабочий конфиг для старта на TypeScript без фреймворка:
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
export default [
eslint.configs.recommended,
...tseslint.configs.recommended,
{ ignores: ["dist/**", "node_modules/**"] },
{
files: ["src/**/*.ts"],
rules: {
"@typescript-eslint/no-explicit-any": "warn",
"no-console": "warn"
}
}
]Короткий чек-лист для любого проекта:
- начни с
recommended— там уже почти всё важное; - добавляй правила постепенно, обсуждая их в команде;
- запускай линтер в CI и в pre-commit;
- используй
--fixна сохранение.
eslint-config и подключай его в каждом воркспейсе плоско.14. Миграция на flat config и defineConfig
Переезд с .eslintrc на flat config — скользкое место. ESLint загружает конфиг как ESM, если в package.json стоит "type": "module", иначе как CommonJS. Чтобы не гадать, используют помощник defineConfig из пакета eslint/config или файл с явным расширением .mjs/.cjs:
// eslint.config.mjs — всегда ESM
import { globalIgnores } from "eslint/config";
export default [
eslint.configs.recommended,
globalIgnores(["dist/**", "node_modules/**"]),
{ files: ["**/*.js"], rules: { "no-unused-vars": "warn" } }
]defineConfig добавляет автодополнение в IDE и проверку типов ключей. Для легаси-проектов есть пакет @eslint/eslintrc с FlatCompat — он переводит старые пресеты в flat-блоки, но убирай его при первой же возможности.
.eslintrc и flat config не работают вместе. ESLint 9 при наличии обоих файлов выбросит ошибку.15. Линтер как аудит безопасности
ESLint незаменим там, где проверяется безопасность JS. Встроенные правила ловят опасные паттерны без сторонних пакетов: no-eval запрещает eval, no-implied-eval — косвенный вызов через setTimeout со строкой, no-new-func — new Function, no-unsafe-finally — риск потери исключения.
rules: {
"no-eval": "error",
"no-implied-eval": "error",
"no-new-func": "error",
"no-unsafe-finally": "error"
}Плагины расширяют картину: eslint-plugin-security предупреждает о небезопасных регулярных выражениях и prototype pollution, для Node-проектов полезен eslint-plugin-security-node, а для React — проверка dangerouslySetInnerHTML через react/no-danger.
16. Производительность и кэш
На крупных проектах полная проверка всех файлов занимает минуты. Ускоряют её тремя способами: кэш, точечный запуск и параллелизм.
npx eslint . --cache --cache-file .eslintcache --max-warnings 0--cacheзапоминает неизменённые файлы и пропускает их при следующем прогоне;lint-stagedв pre-commit проверяет только изменённые файлы;- в монорепо линтер запускают по воркспейсам параллельно, а не одним общим прогоном.
Файл .eslintcache добавь в .gitignore, чтобы не тянуть его в Git. Не перечисляй тяжёлые каталоги в правилах — исключай их заранее через ignores, тогда линтер вообще не откроет эти файлы. Если хочется ускорить сам движок — переходи на свежую мажорную версию: параллельная обработка правил заметно оживляет большие репозитории.
npx eslint . --debug показывает, какие файлы обрабатываются дольше всех и где кэш срабатывает.17. Миграция с JSCS и TSLint
В истории JS было два глобальных «слияния» линтеров: JSCS влился в ESLint (2016), а TSLint официально уступил место typescript-eslint. Если в легаси-проекте остались старые конфиги, миграцию проводят так:
- TSLint: установи
typescript-eslintи перенеси правила, заменяя префиксts-на@typescript-eslint/; - стиль JSCS: подключи готовый пресет (airbnb или standard) через flat-блок, а не дублируй десятки правил вручную;
- после переноса запусти один прогон
--fix— механические правки линтер сделает сам.
// было (TSLint)
"no-implicit-any": true
// стало (typescript-eslint)
"@typescript-eslint/no-explicit-any": "warn"any и несоответствия типов.Что дальше
Потренируй линтер на курсе JavaScript и TypeScript, а при сборке через Vite или Webpack запускай его в CI как один из шагов — тогда плохой код не попадёт в основную ветку GitHub. Про связку с тестами читай Vitest и Jest.