С переходом ESLint к новой системе плоских конфигураций возникла
необходимость сохранить обратную совместимость с огромным количеством
проектов, использующих классический формат .eslintrc.
Адаптеры для старых конфигураций решают задачу плавной миграции,
позволяя использовать существующие правила, плагины и пресеты без
полного переписывания конфигурации.
Старый формат конфигурации ESLint опирался на иерархическую модель наследования:
.eslintrc.json.eslintrc.js.eslintrc.yamlpackage.json (eslintConfig)Эта система поддерживала:
extends для базовых конфигураций;overrides для частичных переопределений;plugin:react/recommended.Новая модель (Flat Config) изменила фундамент:
extends в прежнем виде;Из-за этого старые конфигурации невозможно использовать напрямую без промежуточного слоя преобразования.
Ключевой механизм обратной совместимости реализован в пакете
@eslint/eslintrc через утилиту FlatCompat.
FlatCompat преобразует legacy-конфигурации в flat-структуру, имитируя поведение старой системы.
import { FlatCompat } from "@eslint/eslintrc";
import path from "path";
import { fileURLToPath } from "url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const compat = new FlatCompat({
baseDirectory: __dirname
});
Параметр baseDirectory критически важен:
extends;FlatCompat предоставляет методы, которые эмулируют старую систему расширений.
extendsexport default [
...compat.extends("eslint:recommended"),
...compat.extends("plugin:react/recommended")
];
Каждый вызов:
plugin:...;export default [
...compat.extends("airbnb-base"),
...compat.extends("plugin:@typescript-eslint/recommended")
];
Адаптер автоматически:
node_modules;.eslintrc-структуру;В legacy-системе плагины подключались строками:
{
"plugins": ["react"]
}
FlatCompat преобразует это в явные импорты:
import react from "eslint-plugin-react";
export default [
...compat.plugins("react")
];
При этом важно понимать:
FlatCompat выполняет трансформацию правил в несколько этапов:
Разбор legacy-конфига
Нормализация структуры (extends,
plugins, rules)
Преобразование в flat-объекты:
filesignoreslanguageOptionsrulesСлияние в итоговый массив конфигураций
Пример результата преобразования:
{
files: ["**/*.js"],
rules: {
"no-console": "warn"
}
}
Несмотря на высокий уровень совместимости, существуют ограничения, связанные с архитектурными различиями моделей.
extendsextends в legacy-системе поддерживал сложное дерево
наследования. FlatCompat:
Старые конфиги могли ссылаться на плагины строками без явного импорта. В flat-модели это приводит к необходимости:
Некоторые legacy-конфигурации экспортировали функции:
module.exports = (env) => ({
rules: {
"no-debugger": env.production ? "error" : "off"
}
});
FlatCompat может частично интерпретировать такие случаи, но:
На практике адаптер используется как слой совместимости внутри нового формата:
import { FlatCompat } from "@eslint/eslintrc";
import path from "path";
import { fileURLToPath } from "url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const compat = new FlatCompat({ baseDirectory: __dirname });
export default [
{
ignores: ["dist/**"]
},
...compat.extends("eslint:recommended"),
...compat.extends("plugin:react/recommended"),
{
files: ["**/*.js"],
rules: {
"no-console": "warn"
}
}
];
Такой подход позволяет:
overridesLegacy overrides представлял собой массив условных
конфигураций:
{
"overrides": [
{
"files": ["*.test.js"],
"rules": {
"no-unused-expressions": "off"
}
}
]
}
FlatCompat преобразует это в отдельные объекты:
export default [
...compat.extends("eslint:recommended"),
{
files: ["*.test.js"],
rules: {
"no-unused-expressions": "off"
}
}
];
Особенность заключается в том, что каждый override становится самостоятельным слоем конфигурации.
При использовании @typescript-eslint адаптер учитывает
специфику:
export default [
...compat.extends("plugin:@typescript-eslint/recommended")
];
Преобразование включает:
parserOptions;Однако сложные комбинации:
project-based linting;могут требовать ручной донастройки после адаптации.
Flat model строго линейна, поэтому порядок имеет решающее значение:
export default [
...compat.extends("plugin:react/recommended"),
{
rules: {
"react/prop-types": "off"
}
}
];
Если изменить порядок:
extends могут переопределить локальные
настройки;Адаптеры выполняют промежуточную функцию:
При этом они не являются долгосрочной архитектурой: