Shareable configuration в ESLint представляет собой переиспользуемый набор правил, настроек окружения, плагинов и параметров линтинга, упакованный как npm-пакет. Такой подход позволяет стандартизировать код-стиль внутри команды или экосистемы проектов и централизованно поддерживать единые правила.
Традиционно shareable config оформляется как npm-пакет с именем, начинающимся с префикса:
eslint-config-<name>Пример структуры пакета:
eslint-config-my-config/
├── index.js
├── package.json
├── README.md
Файл index.js содержит экспорт конфигурации ESLint.
Shareable config в классическом формате представляет собой объект, соответствующий ESLint Configuration Schema:
module.exports = {
env: {
browser: true,
node: true,
es2022: true
},
extends: [
"eslint:recommended"
],
parserOptions: {
ecmaVersion: "latest",
sourceType: "module"
},
rules: {
"no-unused-vars": "warn",
"no-console": "off"
}
};
Такая конфигурация может быть расширена другими проектами через поле
extends.
Shareable config часто инкапсулирует плагины, чтобы пользователю не требовалось вручную их подключать.
В package.json плагины указываются как
peerDependencies:
{
"name": "eslint-config-my-config",
"version": "1.0.0",
"peerDependencies": {
"eslint": ">=8.0.0",
"eslint-plugin-import": ">=2.0.0"
}
}
module.exports = {
plugins: ["import"],
rules: {
"import/no-unresolved": "error",
"import/order": "warn"
}
};
Важно: сам пакет eslint-plugin-import не должен
устанавливаться как dependency, если предполагается использование в
составе проектов — он объявляется как peer dependency.
Shareable config часто строится поверх базовых конфигураций ESLint:
module.exports = {
extends: [
"eslint:recommended",
"plugin:import/recommended"
],
rules: {
"import/no-cycle": "error"
}
};
Механизм extends позволяет комбинировать несколько слоёв
конфигурации:
В сложных системах создаётся несколько уровней конфигурации:
eslint-config-base
eslint-config-react
eslint-config-node
eslint-config-typescript
eslint-config-app
Каждый слой расширяет предыдущий:
module.exports = {
extends: [
"eslint-config-base",
"plugin:react/recommended"
],
rules: {
"react/react-in-jsx-scope": "off"
}
};
Shareable config может включать переопределения для отдельных файлов:
module.exports = {
rules: {
"no-console": "warn"
},
overrides: [
{
files: ["*.test.js"],
rules: {
"no-console": "off"
}
}
]
};
Overrides позволяют разделять правила по контексту:
Современный формат ESLint основан на flat configuration, где shareable config экспортирует массив конфигурационных объектов.
export default [
{
files: ["**/*.js"],
languageOptions: {
ecmaVersion: "latest",
sourceType: "module"
},
rules: {
"no-unused-vars": "warn"
}
}
];
import myConfig from "eslint-config-my-config";
export default [
...myConfig
];
Flat config исключает необходимость extends, заменяя его
композиционным объединением массивов.
Shareable config может фиксировать использование парсера:
module.exports = {
parser: "@babel/eslint-parser",
parserOptions: {
requireConfigFile: false,
ecmaFeatures: {
jsx: true
}
}
};
Для TypeScript:
module.exports = {
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint"],
extends: ["plugin:@typescript-eslint/recommended"]
};
Крупные shareable configs часто группируют правила по категориям:
rules: {
"indent": ["error", 2],
"quotes": ["error", "single"],
"semi": ["error", "always"]
}
rules: {
"no-undef": "error",
"no-unused-vars": "warn",
"no-implicit-globals": "error"
}
rules: {
"no-restricted-imports": [
"error",
{
patterns: ["../*"]
}
]
}
{
"name": "eslint-config-company",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"peerDependencies": {
"eslint": ">=8.0.0"
}
}
Стандартный процесс публикации:
npm publish
Shareable config требует строгого semver-подхода:
Изменение поведения правила ESLint считается breaking change, даже если формально конфиг остаётся валидным.
README shareable config обычно фиксирует:
Пример подключения:
module.exports = {
extends: ["eslint-config-company"]
};
Shareable config может разделять конфигурации:
module.exports = {
extends: ["./base"],
overrides: [
{
files: ["src/server/**/*.js"],
env: {
node: true
}
},
{
files: ["src/client/**/*.js"],
env: {
browser: true
}
}
]
};
Для гибкости часто используется паттерн слоёв:
module.exports = {
extends: [
"./rules/base",
"./rules/imports",
"./rules/best-practices"
]
};
Каждый слой представляет отдельный модуль, что облегчает поддержку и тестирование правил.
Неправильное использование dependencies:
"dependencies": {
"eslint-plugin-import": "*"
}
Корректный подход:
"peerDependencies": {
"eslint-plugin-import": ">=2.0.0"
}
Некорректное дублирование правил из расширяемых конфигураций приводит
к конфликтам при объединении extends, особенно при разных
уровнях приоритета конфигураций.
Shareable config обязан учитывать:
Некоторые правила или поля могут быть deprecated, что требует адаптации структуры экспорта и зависимостей.