🐱

Next.js + ESLint(Flat Config) + Prettierの設定をしてみた

に公開

主にESLint周りの設定をしてみたので、設定方法のnoteを残しておきます。

目次

  1. Next.jsプロジェクトの作成
  2. Prettierのセットアップ
  3. ESLintの設定

1. Next.jsプロジェクトの作成

npx create-next-app@latest my-app --yes

私の場合はNext.jsの16.0.1を使用しています。私はnpmを使用していますがお使いのパッケージマネージャーによってこちらのページを参考にプロジェクトを作成してください。

2. Prettierのセットアップ

Prettierはコードを自動的に整形するコードフォーマッターです。コードの保存時やコマンド実行時に、コードを統一されたスタイルに自動整形します。

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

npm install -D prettier eslint-config-prettier

ESLintと併せてPrettierをお使いの場合はeslint-config-prettierをESLintの設定に含める必要があるので、インストールしておきます。後ほどESLintの設定にて解説します。

.prettierrcの作成

プロジェクトルートに.prettierrcを作成:

.prettierrc
{
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "semi": true,
  "singleQuote": true,
  "quoteProps": "as-needed",
  "jsxSingleQuote": false,
  "trailingComma": "es5",
  "bracketSpacing": true,
  "arrowParens": "always",
  "endOfLine": "lf",
  "plugins": ["prettier-plugin-organize-imports"]
}

上記の様にお好みでオプションを設定してください。オプション一覧
私は.prettierrcにjson形式で設定を記述しましたが、その他のファイル形式でも設定できるみたいです。詳しくはこちらをご覧ください。

.prettierignoreの作成

プロジェクトルートに.prettierignoreを作成:

.prettierignore
# Build outputs
.next/
build/
dist/
out/
coverage/

# Dependencies
node_modules/
package-lock.json

# Environment variables
.env*

# Static assets
public/

.prettierignoreはPrettierによりコードを整形してほしくないファイルを指定して無効化することができます。gitignoreと同様の書き方です。詳しくはこちらをご覧ください。

フォーマットを実行

以下のコマンドで現在のディレクトリとそのサブディレクトリ内のPrettierがサポートするすべてのファイルをフォーマットします。

npx prettier . --write

また、vscodeのファイル保存時にもフォーマットを実行することが可能です。
vscode拡張機能のPrettier - Code formatterをインストールしてください。そして、vscodeのsettings.jsonで以下のように設定します。

settings.json
{
  "editor.formatOnSave": true,
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

3. ESLintの設定

ESLint v9.0.0以降ではeslintrcを使用した設定ではなく、以下の様なflat configと呼ばれる設定方法が推奨となっています。

import { defineConfig } from "eslint/config";

export default defineConfig([
	{
		rules: {
			semi: "error",
			"prefer-const": "error",
		},
	},
]);

defineConfigは引数に可変長引数(残余引数)を受け入れることができます。またConfigオブジェクトとConfigオブジェクトを含む配列を受け入れることも可能です。具体的には以下のような引数を受け入れます。

// 複数のConfigオブジェクト
defineConfig(
  { rules: {...} },
  { rules: {...} }
)

// 配列
defineConfig([
  { rules: {...} },
  { rules: {...} }
])

// ネストした配列
defineConfig([
  { rules: {...} },
  [
    { rules: {...} },
    { rules: {...} }
  ]
])

eslint.config.mjsの設定

プロジェクトルートのeslint.config.mjsを以下のように設定してみました。お好みのルールを設定してみてください。

import js from '@eslint/js';
import nextVitals from 'eslint-config-next/core-web-vitals';
import nextTs from 'eslint-config-next/typescript';
import prettier from 'eslint-config-prettier/flat';
import importPlugin from 'eslint-plugin-import';
import unicorn from 'eslint-plugin-unicorn';
import { defineConfig, globalIgnores } from 'eslint/config';
import tseslint from 'typescript-eslint';

const eslintConfig = defineConfig(
  js.configs.recommended,
  tseslint.configs.recommendedTypeChecked,
  {
    languageOptions: {
      parserOptions: {
        projectService: true,
      },
    },
  },

  // Disable type-checked rules for JavaScript files
  {
    files: ['**/*.js', '**/*.mjs', '**/*.cjs'],
    ...tseslint.configs.disableTypeChecked,
  },

  ...nextVitals,
  ...nextTs,
  {
    files: ['**/*.ts', '**/*.tsx'],
    rules: {
      // 暗黙的な型強制を禁止
      'no-implicit-coercion': 'error',

      // テンプレートリテラルを推奨
      'prefer-template': 'error',

      // テンプレート式内の型を厳格にチェック
      '@typescript-eslint/restrict-template-expressions': [
        'error',
        {
          allowNumber: true,
          allowBoolean: true,
          allowAny: false,
          allowNever: false,
          allowNullish: false,
          allowRegExp: false,
        },
      ],

      // 厳格なブール式チェック
      '@typescript-eslint/strict-boolean-expressions': [
        'error',
        {
          allowString: false,
          allowNumber: false,
          allowNullableObject: false,
        },
      ],

      // + 演算子の使用を厳格にチェック
      '@typescript-eslint/restrict-plus-operands': [
        'error',
        {
          allowAny: false,
          allowBoolean: false,
          allowNullish: false,
          allowNumberAndString: false,
          allowRegExp: false,
        },
      ],

      // switch文の網羅性チェック
      '@typescript-eslint/switch-exhaustiveness-check': [
        'error',
        {
          allowDefaultCaseForExhaustiveSwitch: false,
          requireDefaultForNonUnion: false,
        },
      ],

      // メソッド記法を禁止し、プロパティ記法を強制
      '@typescript-eslint/method-signature-style': 'error',

      // 配列のsortに比較関数を必須化
      '@typescript-eslint/require-array-sort-compare': [
        'error',
        {
          ignoreStringArrays: true,
        },
      ],
    },
  },
  {
    plugins: {
      unicorn,
      import: importPlugin,
    },
    rules: {
      // if-elseよりもswitch文を推奨
      'unicorn/prefer-switch': 'error',

      // 循環参照を禁止
      'import/no-cycle': 'error',
    },
  },
  prettier,

  // Override default ignores of eslint-config-next
  globalIgnores(['.next/**', 'out/**', 'build/**', 'next-env.d.ts'])
);

export default eslintConfig;

上記の設定例についての説明をします。

  • js.configs.recommended
    ESLint公式の推奨設定です。eslintrcではeslint:recommendedという名前で設定されていたものです。ESLint v9.0.0以降ではflat configにてjs.configs.recommendedで設定します。recommendedに含まれるルールはこちらをご確認ください。

  • tseslint.configs.recommendedTypeChecked
    typescript-eslintの型チェック付き推奨設定です。含まれるルールはこちらです。
    型チェック付きの設定にはparserの設定が必要になります。これによりESLintが各ソースファイルの型情報をTypeSctiptの型チェックサービスに問い合わせることが可能になります。詳しくはこちらをご覧ください。

  • nextVitals
    Next.jsを使用する際に推奨されるルールセットが含まれています。ルール一覧

  • nextTs
    Next.jsをTypeScriptとともに使用する際の推奨されるルールセットになります。

  • prettier
    2. Prettierのセットアップにてインストールしたeslint-config-prettierです。こちらはPrettierと競合する可能性のあるESLintのスタイルに関する設定を無効化するためのものです。ESLintの設定では後続のオブジェクトが先行するオブジェクトを上書きするようになっているので、こちらの設定を確実に反映させるため一番最後に設定するのが良いと考えます。また、Prettierに関しての設定に問題がないかをチェックできるツールがありますので確認してみるのも良いと思います。公式ドキュメント

    npx eslint-config-prettier path/to/main.js
    

    実行結果:

    No rules that are unnecessary or conflict with Prettier were found.
    ↑この様に表示されればOK
    
  • 個別に設定しているルール
    以下の部分はこれまで説明してきたルールセット(Shared Configs)とは異なり個々のルールをさまざまなオプションで設定しています。

    {
      files: ['**/*.ts', '**/*.tsx'],
      rules: {
        // 暗黙的な型強制を禁止
        'no-implicit-coercion': 'error',
    
        // テンプレートリテラルを推奨
        'prefer-template': 'error',
    
        // テンプレート式内の型を厳格にチェック
        '@typescript-eslint/restrict-template-expressions': [
          'error',
          {
            allowNumber: true,
            allowBoolean: true,
            allowAny: false,
            allowNever: false,
            allowNullish: false,
            allowRegExp: false,
          },
        ],
    
        // 厳格なブール式チェック
        '@typescript-eslint/strict-boolean-expressions': [
          'error',
          {
            allowString: false,
            allowNumber: false,
            allowNullableObject: false,
          },
        ],
    
        // + 演算子の使用を厳格にチェック
        '@typescript-eslint/restrict-plus-operands': [
          'error',
          {
            allowAny: false,
            allowBoolean: false,
            allowNullish: false,
            allowNumberAndString: false,
            allowRegExp: false,
          },
        ],
    
        // switch文の網羅性チェック
        '@typescript-eslint/switch-exhaustiveness-check': [
          'error',
          {
            allowDefaultCaseForExhaustiveSwitch: false,
            requireDefaultForNonUnion: false,
          },
        ],
    
        // メソッド記法を禁止し、プロパティ記法を強制
        '@typescript-eslint/method-signature-style': 'error',
    
        // 配列のsortに比較関数を必須化
        '@typescript-eslint/require-array-sort-compare': [
          'error',
          {
            ignoreStringArrays: true,
          },
        ],
      },
    },
    {
      plugins: {
        unicorn,
        import: importPlugin,
      },
      rules: {
        // if-elseよりもswitch文を推奨
        'unicorn/prefer-switch': 'error',
    
        // 循環参照を禁止
        'import/no-cycle': 'error',
      },
    },
    

    個別でルールを設定する際の参考ドキュメントを以下に残しておきます。

    • plugins:
    • おすすめのルール(以下の記事を参考にさせていただきました。)

ESLintの実行

以下コマンドで実行:

npx eslint .

Discussion