ESLint для Node.js-проектов

ESLint применяется в Node.js-проектах как слой статического анализа, контролирующий корректность кода до его выполнения. В серверной среде Node.js, где отсутствует DOM и браузерные API, а архитектура часто строится на модульности CommonJS или ES Modules, конфигурация линтера приобретает специфические особенности: набор глобальных переменных, окружение выполнения, правила импорта модулей и интеграция с тестовыми фреймворками требуют точной настройки.

ESLint анализирует код на уровне AST (Abstract Syntax Tree), формируемого парсером (по умолчанию Espree). Процесс включает:

  • разбор исходного кода в дерево синтаксических узлов;
  • применение набора правил к каждому узлу;
  • формирование отчёта о нарушениях;
  • автоматическое исправление (если включён --fix и правило поддерживает autofix).

В Node.js-проектах важно учитывать, что стандартные браузерные предположения ESLint не применимы, поэтому конфигурация должна явно отражать серверную среду.

Базовая конфигурация для Node.js

Конфигурационный файл ESLint определяет поведение линтера. Современный формат — eslint.config.js, однако часто используется и классический .eslintrc.

Пример минимальной конфигурации:

module.exports = {
  env: {
    node: true,
    es2022: true
  },
  parserOptions: {
    ecmaVersion: 2022,
    sourceType: "module"
  },
  extends: ["eslint:recommended"],
  rules: {
    semi: ["error", "always"],
    quotes: ["error", "single"]
  }
};

Ключевой элемент — env: { node: true }, который активирует глобальные переменные Node.js: process, __dirname, require, module, Buffer.

CommonJS и ES Modules

Node.js поддерживает две системы модулей, и ESLint должен учитывать обе.

CommonJS

Используются конструкции:

const fs = require('fs');

module.exports = {
  read: () => fs.readFileSync('file.txt', 'utf8')
};

ESLint требует корректной настройки sourceType: "script" либо гибридного режима, если проект смешанный.

ES Modules

При использовании "type": "module" в package.json применяются:

import fs from 'fs';

export function read() {
  return fs.readFileSync('file.txt', 'utf8');
}

В этом случае:

  • sourceType: "module"
  • поддержка import/export
  • необходимость корректного определения расширений файлов

Глобальные переменные Node.js

Node.js предоставляет специфические глобальные объекты, которые ESLint должен распознавать:

  • process — информация о процессе выполнения
  • Buffer — работа с бинарными данными
  • __dirname, __filename — пути файловой системы (в CommonJS)
  • global — глобальная область видимости

При отсутствии env.node = true ESLint будет ошибочно считать их неопределёнными.

Парсер и современные стандарты ECMAScript

Для Node.js-проектов важно соответствие версии ECMAScript, поддерживаемой средой выполнения.

parserOptions: {
  ecmaVersion: "latest",
  sourceType: "module"
}

Использование актуальной версии ECMAScript позволяет применять:

  • optional chaining (?.)
  • nullish coalescing (??)
  • top-level await (в ESM)
  • классы и приватные поля

Правила ESLint для серверной логики

Обработка переменных

Правила, связанные с безопасностью и чистотой кода:

  • no-unused-vars — выявляет неиспользуемые переменные
  • no-undef — предотвращает использование неопределённых идентификаторов
  • no-var — исключает устаревший var

Поток управления

if (user) {
  doSomething();
}

Контролируется правилами:

  • curly — обязательные фигурные скобки
  • eqeqeq — строгое сравнение (=== вместо ==)
  • no-implicit-globals — предотвращение неявных глобальных переменных

Асинхронный код

Node.js активно использует асинхронность:

async function load() {
  const data = await fetchData();
  return data;
}

Полезные правила:

  • no-async-promise-executor
  • require-await
  • no-return-await

Работа с файлами и модулями

Node.js активно взаимодействует с файловой системой, поэтому ESLint часто комбинируется с плагинами:

  • eslint-plugin-import
  • eslint-plugin-node (устаревающий, но встречается)
  • eslint-plugin-n

Пример правил для импортов:

rules: {
  "import/no-unresolved": "error",
  "import/order": ["error", {
    "alphabetize": { "order": "asc" }
  }]
}

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

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

Node.js-проекты часто используют Jest или Mocha. ESLint должен учитывать их глобальные функции.

Для Jest:

env: {
  jest: true
}

Либо через плагины:

  • eslint-plugin-jest

Это позволяет распознавать:

  • describe
  • test
  • expect

Монорепозитории и масштабирование конфигурации

В крупных Node.js-системах ESLint часто применяется в монорепозиториях. Здесь используются:

  • наследование конфигураций
  • overrides
  • shared configs

Пример:

module.exports = {
  overrides: [
    {
      files: ["packages/api/**/*.js"],
      rules: {
        "no-console": "error"
      }
    }
  ]
};

Монорепозитории часто комбинируют ESLint с:

  • Lerna
  • Nx
  • Turborepo

Производительность линтинга

При больших Node.js-кодовых базах критично оптимизировать ESLint:

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

Пример:

eslint . --cache

Кеширование снижает время повторного анализа за счёт хранения результатов AST.

Pre-commit и CI-интеграция

ESLint часто используется как часть цепочки контроля качества:

  • Husky (pre-commit hooks)
  • lint-staged
  • CI pipelines (GitHub Actions, GitLab CI)

Пример конфигурации lint-staged:

{
  "*.js": "eslint --fix"
}

Это позволяет проверять только изменённые файлы перед коммитом.

Обработка ошибок и уровни строгости

ESLint поддерживает три уровня:

  • "off" — правило отключено
  • "warn" — предупреждение
  • "error" — ошибка сборки

В Node.js-проектах обычно строгая политика применяется к:

  • синтаксическим ошибкам
  • потенциальным runtime-bug’ам
  • нарушениям архитектуры

Расширение конфигураций

На практике используется наследование:

extends: [
  "eslint:recommended",
  "plugin:import/recommended",
  "plugin:node/recommended"
]

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

Обработка окружений выполнения

Node.js может работать в различных режимах:

  • сервер API
  • CLI утилиты
  • worker threads
  • serverless функции

Каждое окружение требует разных ESLint-настроек. Например, для CLI часто разрешают:

  • console.log
  • process.exit

В serverless-среде добавляются ограничения на глобальное состояние и файловую систему.

Типизация и ESLint

При использовании TypeScript в Node.js добавляется парсер:

  • @typescript-eslint/parser

И расширенные правила:

  • @typescript-eslint/no-unused-vars
  • @typescript-eslint/explicit-function-return-type

ESLint в таком контексте становится не только линтером, но и частью статической типизации.

Архитектурные паттерны и ESLint

В Node.js ESLint часто закрепляет архитектурные ограничения:

  • запрет на циклические зависимости
  • разделение слоёв (controllers/services/repositories)
  • контроль импортов между модулями

Плагин:

  • eslint-plugin-import с import/no-cycle

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