Глобальная и локальная установка: различия и рекомендации

Модель распространения пакетов в экосистеме Node.js

В Node.js существует два основных способа установки пакетов: глобальный и локальный. Эти подходы определяют, где именно располагается библиотека, как она подключается к проекту и каким образом управляется её версия.

Глобальная установка размещает пакет в системном окружении Node.js, делая его доступным как CLI-инструмент во всех директориях. Локальная установка привязывает пакет к конкретному проекту и сохраняет его в node_modules, обеспечивая изолированность зависимостей.

Для ESLint, как инструмента статического анализа кода JavaScript, выбор способа установки напрямую влияет на воспроизводимость сборки, поведение линтера и интеграцию с инструментами разработки.


Глобальная установка ESLint

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

npm install -g eslint

После установки бинарный файл eslint становится доступен как системная команда. Это позволяет запускать линтер вне контекста конкретного проекта:

eslint file.js
Особенности глобальной установки

Глобальный вариант создаёт единый экземпляр ESLint для всей системы. Это приводит к нескольким характерным особенностям:

  • одна версия ESLint используется для всех проектов;
  • отсутствует привязка к package.json конкретного проекта;
  • обновление версии затрагивает все рабочие окружения одновременно;
  • конфигурация не синхронизируется между проектами автоматически.

Такой подход исторически применялся для упрощения использования CLI-инструментов, однако в современных JavaScript-проектах он считается менее предпочтительным.

Ограничения глобальной установки

Использование глобального ESLint создаёт ряд системных проблем:

  • конфликт версий: разные проекты могут требовать различные версии ESLint и плагинов;
  • непредсказуемость CI/CD: сборочные серверы могут использовать отличающуюся версию линтера;
  • отсутствие изоляции: зависимости не фиксируются в проекте;
  • скрытые ошибки конфигурации: плагины и парсеры могут отсутствовать в глобальной среде.

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


Локальная установка ESLint

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

npm install --save-dev eslint

ESLint сохраняется в devDependencies и становится частью структуры проекта. Запуск осуществляется через локальный бинарный файл:

npx eslint file.js

или через npm-скрипты:

{
  "scripts": {
    "lint": "eslint ."
  }
}
Особенности локальной установки

Локальный вариант обеспечивает строгую привязку к проекту:

  • версия ESLint фиксируется в package.json;
  • зависимости линтера изолированы внутри проекта;
  • конфигурация и плагины управляются совместно с кодовой базой;
  • поведение одинаково на всех машинах и в CI.

Node.js разрешает локальные бинарные файлы через node_modules/.bin, что делает запуск ESLint прозрачным в рамках проекта.


Механизм разрешения зависимостей

При локальной установке Node.js использует алгоритм разрешения модулей, начиная поиск в текущей директории:

project/
 ├─ node_modules/
 │   ├─ eslint/
 │   └─ .bin/eslint
 ├─ package.json

При вызове через npx или npm-скрипт система автоматически обращается к локальной версии.

Глобальная установка, напротив, опирается на системные пути:

  • Linux/macOS: /usr/local/lib/node_modules
  • Windows: %AppData%\npm\node_modules

Это создаёт разделение контекстов между проектами и системой.


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

ESLint активно использует плагины и парсеры, которые тесно связаны с его версией. Например:

  • eslint-plugin-react
  • @typescript-eslint/parser
  • eslint-plugin-import

При глобальной установке возможна ситуация, когда:

  • ESLint обновлён глобально;
  • плагины установлены локально;
  • API плагинов несовместим с версией ESLint.

Это приводит к ошибкам вида:

Error: Failed to load plugin

Локальная установка устраняет этот класс проблем, поскольку все зависимости фиксируются в одном дереве node_modules.


Использование npx и современный подход запуска

Инструмент npx выполняет запуск локально установленного пакета без необходимости ручного указания пути:

npx eslint .

Поведение npx:

  • проверяет локальный node_modules/.bin;
  • при отсутствии может временно загрузить пакет;
  • использует версию, зафиксированную в проекте.

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


Роль package.json и фиксация версии

Локальная установка ESLint фиксирует версию в зависимостях:

{
  "devDependencies": {
    "eslint": "^8.57.0"
  }
}

Символ ^ допускает обновления минорных версий, но сохраняет совместимость API в рамках major-версии.

Фиксация версии обеспечивает:

  • повторяемость анализа кода;
  • предсказуемое поведение линтера;
  • согласованность между разработчиками.

CI/CD и воспроизводимость анализа кода

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

  • устанавливать зависимости через npm ci;
  • использовать зафиксированные версии;
  • исключать влияние глобального окружения.

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


Монорепозитории и единое управление ESLint

В монорепозиториях ESLint устанавливается локально на уровне корня:

repo/
 ├─ packages/
 ├─ package.json
 ├─ node_modules/

Все пакеты используют одну версию ESLint через hoisting (npm, yarn, pnpm). Это обеспечивает:

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

Глобальная установка в монорепозиториях не используется, поскольку не способна обеспечить согласованность между пакетами.


PATH, CLI и поведение командной строки

При глобальной установке команда eslint доступна благодаря добавлению в системный PATH.

При локальной установке доступ осуществляется через:

  • npx eslint
  • npm scripts
  • ./node_modules/.bin/eslint

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


Причины доминирования локальной установки

Современная экосистема JavaScript ориентирована на воспроизводимость и изоляцию зависимостей. Локальная установка ESLint соответствует этим принципам:

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

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