ESLint と Prettier を Flat Config に移行した

Next.js のバージョンアップとあわせて、ESLint と Prettier の設定を Flat Config に移行したメモです。

はじめに

Next.js v15 で対応した ESLint v9 では、Flat Config がデフォルトになりました。 Flat Config では、従来の .eslintrc.*.eslintignore に代わり、eslint.config.mjs に設定をまとめます。


Next.js 15 + ESLint + Prettier の Flat Config 設定方法

必要なパッケージをインストール

まずは、必要なパッケージをインストールします。

pnpm add -D eslint prettier eslint-config-prettier eslint-plugin-import eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-unused-imports eslint-plugin-tailwindcss @next/eslint-plugin-next typescript-eslint

typescript-eslint 公式ドキュメント にも書かれている通り、レガシーとなった @typescript-eslint/parser@typescript-eslint/eslint-plugin は、削除しておきます。

pnpm remove @typescript-eslint/parser @typescript-eslint/eslint-plugin

また、VSCode で ESLint を有効にするために、eslint.useFlatConfigtrue に設定しておきます (後述)

ESLint の設定 (eslint.config.mjs)

eslint.config.mjs をプロジェクトのルートに作成し、以下のように設定します。

eslint.config.mjs
// @ts-check
 
import eslintPluginNext from '@next/eslint-plugin-next';
import eslintConfigPrettier from 'eslint-config-prettier';
import * as eslintPluginImport from 'eslint-plugin-import';
import eslintPluginReact from 'eslint-plugin-react';
import eslintPluginReactHooks from 'eslint-plugin-react-hooks';
import tailwindcss from 'eslint-plugin-tailwindcss';
import eslintPluginUnusedImports from 'eslint-plugin-unused-imports';
import tsEslint from 'typescript-eslint';
 
export default [
  {
    files: ['*.js', '*.jsx', '*.ts', '*.tsx'],
  },
  {
    ignores: [
      '**/build/',
      '**/bin/',
      '**/dist/',
      '**/obj/',
      '**/out/',
      '**/.next/',
      '**/node_modules/',
    ],
  },
  eslintPluginReact.configs.flat.recommended,
  eslintPluginReact.configs.flat['jsx-runtime'],
  {
    plugins: {
      'react-hooks': eslintPluginReactHooks,
      '@next': eslintPluginNext,
    },
    ...eslintPluginReactHooks.configs.recommended.rules,
    ...eslintPluginNext.configs.recommended.rules,
    ...eslintPluginNext.configs['core-web-vitals'].rules,
    '@next/next/no-img-element': 'error',
    'react/prop-types': 'off',
  },
  tsEslint.configs.recommended,
  {
    languageOptions: {
      parser: tsEslint.parser,
      parserOptions: {
        project: './tsconfig.json',
      },
    },
    rules: {
      '@typescript-eslint/no-unused-vars': [
        'warn',
        { argsIgnorePattern: '^_' },
      ],
      '@typescript-eslint/explicit-function-return-type': 'off',
    },
  },
  tailwindcss,
  {
    plugins: {
      import: eslintPluginImport,
    },
    rules: {
      'import/order': [
        'error',
        {
          groups: [
            'builtin',
            'external',
            'internal',
            'parent',
            'sibling',
            'index',
            'object',
            'type',
          ],
          alphabetize: {
            order: 'asc',
            caseInsensitive: true,
          },
          'newlines-between': 'never',
        },
      ],
      'import/newline-after-import': 'error',
      'import/no-duplicates': 'error',
    },
  },
  {
    plugins: {
      'unused-imports': eslintPluginUnusedImports,
    },
    rules: {
      'unused-imports/no-unused-imports': 'error',
    },
  },
  eslintConfigPrettier,
];

eslint-config-next ではなく @next/eslint-plugin-next, eslint-plugin-react, eslint-plugin-react-hooks を導入しているのは、 こちら で議論されているように、Flat Config の対応状況によるものです。

なお、Prettier との競合を防ぐため、 eslint-config-prettier は最後に追加しています。

Prettier の設定 (prettier.config.mjs)

次に、Prettier の設定を prettier.config.mjs に記述します。

prettier.config.mjs
// @ts-check
 
/**
 * @type {import("prettier").Config}
 */
export default {
  printWidth: 80,
  tabWidth: 2,
  plugins: ['prettier-plugin-tailwindcss'],
  semi: true,
  singleQuote: true,
  trailingComma: 'es5',
  bracketSpacing: true,
};

Tailwind CSS のクラス順序を自動整理するため に、prettier-plugin-tailwindcss を入れています。

ESLint とは異なり、ignore 設定については、これまで通りに .prettierignore に記述します。

VSCode の設定 (.vscode/settings.json)

VSCode で保存時に ESLint + Prettier の自動フォーマットを適用するため、.vscode/settings.json に以下を追加します。

.vscode/settings.json
{
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
  "eslint.enable": true,
  "eslint.useFlatConfig": true,
  "files.insertFinalNewline": true
}

ESLint & Prettier の動作確認

ESLint のチェック

pnpm eslint . --fix

Prettier のフォーマット

pnpm prettier --write .

まとめ

Flat Config 移行により、以前よりもシンプルに設定を書けるようになりました。 最近なにかと話題の(?) Biome も気になっているので、今度試して比較してみます。