Плагин eslint-plugin-n

Плагин ESLint-plugin-n представляет собой набор правил для статического анализа кода, ориентированных на среду Node.js. Его основная задача — контроль корректного использования Node.js API, предотвращение устаревших паттернов и выявление ошибок, связанных с особенностями серверного JavaScript.

eslint-plugin-n применяется для анализа серверного JavaScript-кода, где критичны такие аспекты, как:

  • корректное использование модулей CommonJS и ES Modules;
  • соблюдение совместимости с версиями Node.js;
  • предотвращение использования устаревших или удалённых API;
  • контроль за особенностями асинхронного исполнения в Node.js;
  • предотвращение типичных ошибок окружения (process, globals, import/export).

Плагин исторически вырос как продолжение и развитие решений, связанных с eslint-plugin-node, и фактически заменяет его в современных конфигурациях ESLint.

Архитектура правил

eslint-plugin-n организован как набор независимых правил, сгруппированных по функциональным областям. Каждое правило представляет собой модуль, анализирующий AST (Abstract Syntax Tree) и применяющий проверки к конкретным узлам кода.

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

  • модули и импорты;
  • совместимость версий Node.js;
  • глобальные переменные Node.js;
  • API и встроенные объекты;
  • асинхронные операции и callback-паттерны.

Каждое правило имеет строгую конфигурацию, уровень severity (off, warn, error) и дополнительные опции, позволяющие адаптировать поведение под конкретный runtime.

Установка и подключение

Установка осуществляется через npm или аналогичные менеджеры пакетов:

npm install eslint-plugin-n --save-dev

Подключение в конфигурации ESLint:

Legacy конфигурация (.eslintrc)

{
  "plugins": ["n"],
  "extends": ["plugin:n/recommended"]
}

Flat config (ESLint 9+)

import n from "eslint-plugin-n";

export default [
  n.configs.recommended
];

Flat config позволяет более гибко комбинировать правила и снижает зависимость от строковых конфигураций.

Основные правила плагина

Контроль версий Node.js

Одно из ключевых направлений — проверка API в зависимости от указанной версии Node.js.

Правило n/no-unsupported-features/node-builtins анализирует использование встроенных модулей и сопоставляет их с целевой версией runtime.

Типичный сценарий:

  • использование fs/promises в старых версиях Node.js;
  • применение современных методов crypto без полифилов;
  • вызов API, отсутствующих в LTS-версии.

Модули и импорты

Правила, связанные с модулями:

  • n/no-missing-import — проверка существования импортируемых модулей;
  • n/no-extraneous-import — выявление импортов, отсутствующих в dependencies;
  • n/no-unpublished-import — контроль использования внутренних файлов пакета.

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

CommonJS и ES Modules

eslint-plugin-n активно контролирует корректность смешивания систем модулей:

  • запрет некорректного использования require в ESM-контексте;
  • контроль import/export в CommonJS-проектах;
  • проверка расширений файлов при ESM-импортах.

Правило n/no-unsupported-features/es-syntax особенно важно при миграции между системами модулей.

Совместимость с версиями Node.js

Одна из наиболее значимых функций — декларативное указание целевой версии Node.js через конфигурацию:

{
  "settings": {
    "node": {
      "version": ">=18.0.0"
    }
  }
}

На основе этого параметра плагин строит граф допустимых API и синтаксических возможностей.

Проверки включают:

  • синтаксис языка (optional chaining, nullish coalescing);
  • встроенные модули;
  • глобальные объекты;
  • experimental API.

Работа с глобальными объектами

Node.js предоставляет специфические глобальные объекты (process, Buffer, __dirname, __filename). eslint-plugin-n регулирует их использование:

  • n/no-deprecated-api — запрет устаревших глобальных методов;
  • n/prefer-global/process — контроль явного использования process;
  • n/prefer-global/buffer — унификация работы с Buffer.

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

Асинхронность и callback-паттерны

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

  • корректность callback-аргументов;
  • предотвращение callback hell;
  • контроль забытых ошибок в callback-функциях.

Особое внимание уделяется Node-style callbacks (err, data) и их правильной обработке.

Совместимость с ESLint Flat Config

Flat config требует явного импорта плагина и его конфигурации:

import n from "eslint-plugin-n";

export default [
  {
    files: ["**/*.js"],
    plugins: { n },
    rules: {
      ...n.configs.recommended.rules
    }
  }
];

В этой модели каждая часть конфигурации становится декларативной, а плагин интегрируется как объект, а не строковый идентификатор.

Интеграция с TypeScript-проектами

Хотя eslint-plugin-n не ориентирован напрямую на TypeScript, он часто используется совместно с:

  • @typescript-eslint/parser;
  • @typescript-eslint/eslint-plugin.

Основные конфликты возникают в области:

  • разрешения модулей;
  • интерпретации типов импортов;
  • проверки существования файлов.

Для корректной работы важно синхронизировать настройки резолвера с TypeScript compiler options.

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

eslint-plugin-n оптимизирован для минимального влияния на время линтинга:

  • AST-обход выполняется только для релевантных узлов;
  • большинство проверок имеют O(1) сложность;
  • кеширование результатов резолва модулей.

Основная нагрузка возникает при глубоких деревьях импортов и большом количестве файлов в monorepo.

Типичные ошибки конфигурации

Распространённые проблемы при использовании:

  • отсутствие указания версии Node.js, что отключает часть проверок;
  • конфликт с eslint-plugin-import при дублирующих правилах;
  • некорректная настройка module resolution;
  • смешивание CommonJS и ESM без явной стратегии миграции.

Практические сценарии применения

В реальных проектах плагин используется для:

  • серверных API на Node.js (Express, Fastify, NestJS);
  • CLI-инструментов;
  • serverless-функций;
  • монорепозиториев с общими библиотеками.

Он особенно полезен в проектах с длительным жизненным циклом, где критична обратная совместимость с LTS-версиями Node.js.