Плагин ESLint может содержать не только пользовательские правила, процессоры и наборы окружений, но и готовые конфигурации. Экспорт конфигураций позволяет поставлять вместе с плагином заранее настроенные наборы правил, которые пользователи могут подключать одной строкой вместо ручной настройки десятков параметров.
Такой подход широко используется в экосистеме ESLint. Многие популярные плагины предоставляют несколько конфигураций одновременно:
Основная идея заключается в том, что автор плагина определяет оптимальный набор правил и публикует его как часть пакета.
Типичная структура проекта выглядит следующим образом:
eslint-plugin-example/
├── lib/
│ ├── rules/
│ │ ├── no-console-log.js
│ │ └── require-description.js
│ └── index.js
├── package.json
└── README.md
Файл index.js обычно является точкой входа плагина и
экспортирует все доступные сущности.
Пример:
const noConsoleLog = require("./rules/no-console-log");
const requireDescription = require("./rules/require-description");
module.exports = {
rules: {
"no-console-log": noConsoleLog,
"require-description": requireDescription
},
configs: {
recommended: {
rules: {
"example/no-console-log": "error",
"example/require-description": "warn"
}
}
}
};
В объекте configs содержатся все конфигурации, доступные
пользователям.
ESLint ожидает, что экспортируемые конфигурации будут находиться в
свойстве configs.
Простейший вариант:
module.exports = {
configs: {
recommended: {
rules: {
"example/no-console-log": "error"
}
}
}
};
После публикации плагина пользователь сможет подключить такую конфигурацию через механизм расширения настроек.
Для старого формата конфигураций:
module.exports = {
extends: [
"plugin:example/recommended"
]
};
Здесь:
example — имя плагина без префикса
eslint-plugin-;recommended — имя экспортированной конфигурации.Наиболее распространённые имена:
| Имя | Назначение |
|---|---|
recommended |
Рекомендуемый набор правил |
all |
Все правила плагина |
strict |
Максимально строгие проверки |
typescript |
Настройки для TypeScript |
react |
Настройки для React |
node |
Настройки для Node.js |
test |
Настройки для тестовой среды |
Плагин может экспортировать любое количество конфигураций.
Пример:
module.exports = {
configs: {
recommended: {},
strict: {},
all: {}
}
};
Подключение:
extends: [
"plugin:example/recommended",
"plugin:example/strict"
]
Практически каждый серьёзный ESLint-плагин предоставляет конфигурацию
recommended.
Её задача — включать правила, которые:
Пример:
module.exports = {
configs: {
recommended: {
rules: {
"example/no-console-log": "error",
"example/require-description": "warn"
}
}
}
};
Обычно в такую конфигурацию не включают слишком спорные правила оформления кода.
Конфигурация all включает все правила плагина.
Пример:
module.exports = {
configs: {
all: {
rules: {
"example/no-console-log": "error",
"example/require-description": "error",
"example/max-function-lines": "error",
"example/no-inline-comment": "error"
}
}
}
};
Особенности:
Во многих популярных плагинах конфигурация all считается
нестабильной, поскольку новые версии могут автоматически включать новые
правила.
При описании правил необходимо указывать полный идентификатор.
Неправильно:
rules: {
"no-console-log": "error"
}
Правильно:
rules: {
"example/no-console-log": "error"
}
Префикс должен совпадать с именем плагина.
Если пакет называется:
eslint-plugin-example
то имя пространства правил будет:
example
Итоговое имя:
example/no-console-log
Часто один и тот же набор правил публикуется в нескольких вариантах.
Пример:
module.exports = {
configs: {
recommended: {
rules: {
"example/no-console-log": "warn"
}
},
strict: {
rules: {
"example/no-console-log": "error",
"example/require-description": "error"
}
}
}
};
Пользователь самостоятельно выбирает необходимый уровень контроля.
Конфигурация может содержать любые параметры ESLint.
Например:
module.exports = {
configs: {
recommended: {
parserOptions: {
ecmaVersion: "latest",
sourceType: "module"
},
rules: {
"example/no-console-log": "error"
}
}
}
};
Это избавляет пользователей от необходимости повторять типовые настройки.
Современный ESLint использует формат Flat Config.
В этом случае экспортируемая конфигурация может выглядеть так:
const plugin = {
rules: {
"no-console-log": noConsoleLog
},
configs: {
recommended: {
plugins: {
example: null
},
rules: {
"example/no-console-log": "error"
}
}
}
};
На практике структура зависит от версии ESLint и способа публикации плагина.
Для Flat Config обычно экспортируется полноценный объект конфигурации, совместимый с новым API.
Современный подход:
const plugin = {
rules: {
"no-console-log": noConsoleLog
}
};
plugin.configs = {
recommended: {
plugins: {
example: plugin
},
rules: {
"example/no-console-log": "error"
}
}
};
module.exports = plugin;
Подключение:
const examplePlugin = require("eslint-plugin-example");
module.exports = [
examplePlugin.configs.recommended
];
Такой подход становится всё более распространённым после перехода ESLint на плоские конфигурации.
Чтобы избежать дублирования, одна конфигурация может строиться поверх другой.
Пример:
const recommendedRules = {
"example/no-console-log": "error"
};
module.exports = {
configs: {
recommended: {
rules: recommendedRules
},
strict: {
rules: {
...recommendedRules,
"example/require-description": "error"
}
}
}
};
Преимущества:
В крупных плагинах конфигурации обычно выносятся в отдельную директорию.
Структура:
lib/
├── configs/
│ ├── recommended.js
│ ├── strict.js
│ └── all.js
├── rules/
└── index.js
Файл recommended.js:
module.exports = {
rules: {
"example/no-console-log": "error"
}
};
Файл index.js:
const recommended = require("./configs/recommended");
const strict = require("./configs/strict");
module.exports = {
rules: {},
configs: {
recommended,
strict
}
};
Такой подход особенно полезен при большом количестве конфигураций.
Конфигурация может использовать другие плагины и расширения.
Пример:
module.exports = {
configs: {
recommended: {
extends: [
"eslint:recommended"
],
rules: {
"example/no-console-log": "error"
}
}
}
};
Это позволяет публиковать готовые комплексные решения.
Распространённая практика — выпуск специализированных конфигураций.
Для React:
module.exports = {
configs: {
react: {
rules: {
"example/no-console-log": "error",
"example/react-component-name": "warn"
}
}
}
};
Для Node.js:
module.exports = {
configs: {
node: {
rules: {
"example/no-process-exit": "error"
}
}
}
};
Для тестов:
module.exports = {
configs: {
test: {
rules: {
"example/no-focused-test": "error"
}
}
}
};
Подобное разделение позволяет адаптировать один плагин под разные типы проектов.
Если правил много, конфигурацию all можно генерировать
программно.
Пример:
const rules = {
"no-console-log": require("./rules/no-console-log"),
"require-description": require("./rules/require-description")
};
const allRules = {};
for (const ruleName of Object.keys(rules)) {
allRules[`example/${ruleName}`] = "error";
}
module.exports = {
rules,
configs: {
all: {
rules: allRules
}
}
};
Преимущества:
Каждая экспортируемая конфигурация должна быть подробно описана.
Обычно документация содержит:
Пример описания:
plugin:example/recommended
Включает:
Пример подключения:
extends: [
"plugin:example/recommended"
]
Хорошо документированные конфигурации значительно упрощают внедрение плагина и уменьшают количество ошибок при настройке.
Неправильно:
rules: {
"no-console-log": "error"
}
Правильно:
rules: {
"example/no-console-log": "error"
}
Пакет:
eslint-plugin-example
Правило:
example/no-console-log
а не:
eslint-plugin-example/no-console-log
Неправильно:
rules: {
"example/unknown-rule": "error"
}
Все правила должны присутствовать в секции:
rules: {
"unknown-rule": ruleImplementation
}
Проблема:
recommended.js
импортирует:
index.js
а index.js импортирует:
recommended.js
Подобные циклы нередко приводят к частично инициализированным объектам и трудноуловимым ошибкам.
Не следует одновременно использовать несовместимые подходы для Legacy Config и Flat Config без явного разделения. Для поддержки разных поколений ESLint обычно публикуются отдельные экспортируемые варианты конфигураций с чётко определённым назначением и документацией.