Публикация конфигурации в npm

Публикуемая конфигурация ESLint оформляется как отдельный npm-пакет, предназначенный для переиспользования в различных проектах. Основой служит набор правил, пресетов и подключаемых плагинов, инкапсулированных в единый конфигурационный модуль.

Типовая структура пакета включает следующие элементы:

  • файл конфигурации (index.js, eslint.config.js или .eslintrc.js)
  • package.json с метаданными и зависимостями
  • описание правил и пресетов
  • при необходимости — дополнительные вспомогательные модули (shared rules, utils)

Ключевая особенность publishable-конфигурации заключается в её предсказуемом поведении при подключении через extends.


Формирование имени npm-пакета

Для конфигураций ESLint используется строго определённая схема именования:

  • базовый формат: eslint-config-*
  • scoped-формат: @scope/eslint-config

Примеры:

  • eslint-config-standard
  • eslint-config-airbnb-base
  • @company/eslint-config

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

{
  "extends": "company"
}

или для scoped-пакета:

{
  "extends": "@company"
}

ESLint автоматически резолвит такие пакеты по соглашению именования.


package.json как основа публикации

Конфигурационный пакет ESLint требует корректного описания метаданных npm. Основные поля определяют поведение при установке и совместимость.

{
  "name": "eslint-config-company",
  "version": "1.0.0",
  "main": "index.js",
  "peerDependencies": {
    "eslint": ">=8.0.0"
  },
  "keywords": [
    "eslint",
    "eslintconfig",
    "lint"
  ],
  "license": "MIT"
}

peerDependencies

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

Дополнительно иногда фиксируются версии плагинов:

{
  "peerDependencies": {
    "eslint": ">=8.0.0",
    "eslint-plugin-import": ">=2.25.0"
  }
}

Legacy-конфигурация через .eslintrc

Традиционный формат конфигурации основан на экспорте объекта:

module.exports = {
  rules: {
    semi: ["error", "always"],
    quotes: ["error", "single"]
  },
  env: {
    node: true,
    es2022: true
  }
};

При публикации такой пакет подключается через extends:

{
  "extends": "company"
}

ESLint автоматически ищет eslint-config-company в node_modules.


Flat config и современный формат публикации

В новых версиях ESLint используется flat config (eslint.config.js), где конфигурация экспортируется массивом объектов:

export default [
  {
    files: ["**/*.js"],
    rules: {
      semi: "error",
      quotes: ["error", "single"]
    }
  }
];

Публикуемые конфигурации в таком формате чаще экспортируют готовый массив или функцию:

export default [
  ...baseConfig,
  {
    rules: {
      "no-console": "warn"
    }
  }
];

Для переиспользования в других пакетах применяется импорт:

import companyConfig from "eslint-config-company";

Инкапсуляция правил и модульная структура

Большие конфигурации разделяются на слои:

  • базовые правила (base)
  • правила JavaScript
  • правила TypeScript
  • правила React/Vue
  • интеграция с Prettier

Пример структуры:

eslint-config-company/
  base.js
  react.js
  typescript.js
  index.js

index.js агрегирует конфигурации:

module.exports = [
  require("./base"),
  require("./typescript"),
  require("./react")
];

Плагины и зависимость от внешних правил

Конфигурации ESLint часто зависят от плагинов:

  • eslint-plugin-import
  • eslint-plugin-react
  • eslint-plugin-promise

Такие зависимости фиксируются в peerDependencies, чтобы избежать конфликтов версий.

Пример конфигурации правил:

module.exports = {
  plugins: ["import"],
  rules: {
    "import/order": "error",
    "import/no-unresolved": "error"
  }
};

Подключение через extends

Публикуемая конфигурация активируется через механизм наследования:

{
  "extends": ["company", "company/react"]
}

Поддерживается цепочка расширений, где каждая следующая конфигурация дополняет или переопределяет предыдущую.

При многоуровневой архитектуре используются отдельные entry points:

  • eslint-config-company
  • eslint-config-company/react
  • eslint-config-company/node

Версионирование конфигураций

Для npm-пакетов ESLint применяется семантическое версионирование:

  • MAJOR — несовместимые изменения правил
  • MINOR — добавление новых правил без нарушения совместимости
  • PATCH — исправления и уточнения

Изменение поведения линтинга считается breaking change даже при изменении одного правила с warn на error.


Публикация в npm registry

Публикация конфигурации осуществляется через npm CLI. Перед публикацией фиксируется версия пакета:

npm version minor

Далее выполняется публикация:

npm publish

Для scoped-пакетов требуется указание публичного доступа:

npm publish --access public

Политика доступа и scoped-конфигурации

Scoped-пакеты позволяют изолировать конфигурации внутри организации:

@company/eslint-config

Преимущества:

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

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

{
  "extends": "@company"
}

Расширяемость и переопределение правил

Публикуемая конфигурация должна поддерживать переопределение на уровне проекта:

{
  "extends": "company",
  "rules": {
    "quotes": ["error", "double"]
  }
}

Механизм merge конфигураций выполняется ESLint по приоритету:

  1. локальные правила проекта
  2. правила из extends
  3. базовые значения плагинов

Поддержка нескольких окружений

Конфигурации часто разделяются по средам выполнения:

  • Node.js
  • браузер
  • тестовые среды (Jest, Vitest)

Пример:

module.exports = {
  env: {
    browser: true,
    node: true,
    jest: true
  }
};

В модульной публикации это выносится в отдельные entry points:

  • eslint-config-company/node
  • eslint-config-company/browser

Управление зависимостями конфигурации

Корректная публикация требует строгого разделения:

  • dependencies — редко используются
  • peerDependencies — ESLint и плагины
  • devDependencies — тестирование и линтинг самого пакета

Пример:

{
  "devDependencies": {
    "eslint": "^8.0.0"
  }
}

Тестирование публикуемой конфигурации

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

  • наличие конфликтов между плагинами
  • валидность синтаксиса конфигурации
  • совместимость с указанной версией ESLint

Тестовые проекты используют локальное подключение пакета через npm link или workspace-монорепозиторий.


Монорепозитории и распределённые конфигурации

В крупных проектах конфигурации публикуются как набор пакетов:

packages/
  eslint-config-base
  eslint-config-react
  eslint-config-node

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


Совместимость с плагинами и экосистемой

Конфигурации ESLint тесно связаны с плагинами и форматтерами. Часто требуется синхронизация:

  • версии ESLint
  • версии eslint-plugin-*
  • конфигурации Prettier

Несовместимость версий приводит к конфликтам в разрешении правил и различиям в поведении линтера между проектами.