JavaScriptNode.jsESLint

@eslint/migrate-config を使って legacy ESLint configuration file format を new ESLint configuration file format に変換する

はじめに

ESLint v8.21.0 から追加された Flat Config。 ESLint v9 から Flat Config がデフォルトとして扱われるようになりました。

ESLint v9 で従来の legacy ESLint configuration file format を使いたい場合は、 ESLINT_USE_FLAT_CONFIGfalse に設定すれば利用可能ですが、 @eslint/migrate-config を利用すれば、簡単に移行することができます。

注意

@eslint/migrate-config は 2024/11 時点以下のファイルフォーマットのみ対応しています。

  • eslintrc
  • eslintrc.json
  • eslintrc.yml

.eslintrc.js, .eslintrc.cjs, .eslintrc.mjs でも移行することはできますが、完全に移行できないことに注意する必要があります。

使用方法

npx を利用すればパッケージを追加せず利用することが可能です。

npx @eslint/migrate-config .eslintrc.json

移行検証

いくつか @eslint/migrate-config を利用して移行してみました。

remix-run/remix/templates/remix

remix-run/remix/templates/remix 内の templates/remix/.eslintrc.cjs を移行してみます。

> npx @eslint/migrate-config .eslintrc.cjs
Need to install the following packages:
@eslint/migrate-config@1.3.3
Ok to proceed? (y) y


Migrating .eslintrc.cjs

WARNING: This tool does not yet work great for .eslintrc.(js|cjs|mjs) files.
It will convert the evaluated output of our config file, not the source code.
Please review the output carefully to ensure it is correct.


Wrote new config to ./eslint.config.mjs

You will need to install the following packages to use the new config:
- globals
- @eslint/compat
- @eslint/js
- @eslint/eslintrc

You can install them using the following command:

npm install globals @eslint/compat @eslint/js @eslint/eslintrc -D

.eslintrc.cjs から eslint.config.mjs が生成されました。 また、 console に記載されている通り、 globals 等のパッケージを追加する必要があります。

移行前のファイル

移行後のファイル

import globals from "globals";
import { fixupConfigRules, fixupPluginRules, fixupConfigRules } from "@eslint/compat";
import react from "eslint-plugin-react";
import jsxA11Y from "eslint-plugin-jsx-a11y";
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import _import from "eslint-plugin-import";
import tsParser from "@typescript-eslint/parser";
import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
    baseDirectory: __dirname,
    recommendedConfig: js.configs.recommended,
    allConfig: js.configs.all
});

export default [{
    ignores: ["!**/.server", "!**/.client"],
}, ...compat.extends("eslint:recommended"), {
    languageOptions: {
        globals: {
            ...globals.browser,
            ...globals.commonjs,
        },

        ecmaVersion: "latest",
        sourceType: "module",

        parserOptions: {
            ecmaFeatures: {
                jsx: true,
            },
        },
    },
}, ...fixupConfigRules(compat.extends(
    "plugin:react/recommended",
    "plugin:react/jsx-runtime",
    "plugin:react-hooks/recommended",
    "plugin:jsx-a11y/recommended",
)).map(config => ({
    ...config,
    files: ["**/*.{js,jsx,ts,tsx}"],
})), {
    files: ["**/*.{js,jsx,ts,tsx}"],

    plugins: {
        react: fixupPluginRules(react),
        "jsx-a11y": fixupPluginRules(jsxA11Y),
    },

    settings: {
        react: {
            version: "detect",
        },

        formComponents: ["Form"],

        linkComponents: [{
            name: "Link",
            linkAttribute: "to",
        }, {
            name: "NavLink",
            linkAttribute: "to",
        }],

        "import/resolver": {
            typescript: {},
        },
    },
}, ...fixupConfigRules(compat.extends(
    "plugin:@typescript-eslint/recommended",
    "plugin:import/recommended",
    "plugin:import/typescript",
)).map(config => ({
    ...config,
    files: ["**/*.{ts,tsx}"],
})), {
    files: ["**/*.{ts,tsx}"],

    plugins: {
        "@typescript-eslint": fixupPluginRules(typescriptEslint),
        import: fixupPluginRules(_import),
    },

    languageOptions: {
        parser: tsParser,
    },

    settings: {
        "import/internal-regex": "^~/",

        "import/resolver": {
            node: {
                extensions: [".ts", ".tsx"],
            },

            typescript: {
                alwaysTryTypes: true,
            },
        },
    },
}, {
    files: ["**/.eslintrc.cjs"],

    languageOptions: {
        globals: {
            ...globals.node,
        },
    },
}];

実行完了後に移行前のファイル .eslintrc.cjs は手動で削除してください。

rm .eslintrc.cjs

mziyut/honkit-plugin-prism

mziyut/honkit-plugin-prism.eslintrc も移行してみます。 https://github.com/mziyut/honkit-plugin-prism/blob/main/.eslintrc

> npx @eslint/migrate-config .eslintrc

Migrating .eslintrc

Wrote new config to ./eslint.config.mjs

You will need to install the following packages to use the new config:
- @eslint/js
- @eslint/eslintrc

You can install them using the following command:

npm install @eslint/js @eslint/eslintrc -D

移行前のファイル

---
extends: eslint-config-semistandard
rules:
  padded-blocks: 0
  space-before-function-paren: 0

移行後のファイル

import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
    baseDirectory: __dirname,
    recommendedConfig: js.configs.recommended,
    allConfig: js.configs.all
});

export default [...compat.extends("eslint-config-semistandard"), {
    rules: {
        "padded-blocks": 0,
        "space-before-function-paren": 0,
    },
}];

Ref