言語を切り替える
テーマを切り替える

Next.js エンジニアリング設定:ESLint + Prettier + Husky オールインワン構築ガイド

金曜の夜の悪夢

先週の金曜日の夜のことを覚えていますか? パソコンを閉じて帰ろうとしたその時、Slackで技術責任者からメッセージが届きました。「君のPR、フォーマットの問題が多すぎるよ。直してから再提出してくれる?」GitHubを開くと、画面いっぱいの赤いdiff。ダブルクォートを使っているところもあれば、インデントがバラバラなところもありました。

正直、無力感に襲われました。コミットする前に npm run lint を実行したはずなのに、なぜまだ問題があるのでしょうか? さらに気まずかったのは、チームの別の同僚も似たような状況に陥っていたことです。彼のコードロジックは完璧でしたが、フォーマットが私と違っていたため、マージ時に無意味なコンフリクトが大量発生してしまいました。

こんな経験はありませんか? コードはちゃんと書いたのに、フォーマットの問題でPRレビューを行ったり来たりして、みんなの時間を無駄にする。その時私は思いました。「機械にこの面倒な作業を自動でやらせる、恒久的な解決策はないものか?」

答えはあります。ESLint + Prettier + Husky の最強コンボです。

なぜこの3つのツールが必要なのか?

正直なところ、最初にこの3つの名前を聞いた時は、少し複雑そうだと感じました。しかし、しばらく使ってみると、もう戻れなくなりました。それぞれの価値について説明させてください。

ESLint:コード品質の守護者

多くの人はESLintを単なるフォーマットチェックツールだと思っていますが、実際の最も重要な役割は潜在的なコードの問題を捕捉することです。

例えば、Next.js公式はHTMLの <img> タグではなく <Image> コンポーネントの使用を推奨しています。前者は自動最適化機能があるからです。もしうっかり <img> を書いてしまったら、ESLintはすぐにエラー警告を出してくれます:

Error: Do not use <img>. Use Image from 'next/image' instead.

このような警告のおかげで、開発段階でパフォーマンスの落とし穴を回避できます。リリース後に画像の読み込みが遅いことに気づいて最適化するよりも、はるかに効率的です。

Next.js 15 はデフォルトで ESLint を有効にしていますが、その価値を最大限に引き出すには正しい設定が必要です。

Prettier:フォーマットの究極の解決策

ESLintはコードのロジックと品質に焦点を当て、Prettierはコードのフォーマットに焦点を当てています。両者の役割は明確で、混同すべきではありません。

私たちのチームでは以前、フォーマットの問題でよく議論になりました。シングルクォート派とダブルクォート派、2スペース派と4スペース派。コードレビューのたびに、これらのどうでもいい詳細について議論するのは、本当に時間の無駄です。

Prettierを設定すれば、これらの問題は完全に消えます。プロジェクト開始時にチームメンバーとルール(例:シングルクォート統一、2スペースインデント)を決めておけば、あとはPrettierが自動的にすべてのコードをフォーマットしてくれます。一度設定すれば、一生の利益になります

Husky:自動化の鍵

ツールが優れていても、手動で実行しなければならないなら、誰かが必ず忘れます。

私自身、何度か経験があります。ローカル開発時に npm run lint を実行し忘れてコードをコミットしてしまい、CIプロセスが失敗してチーム全体のデプロイをブロックしてしまったことがありました。あの気まずさは二度と味わいたくありません。

Huskyの役割は、あなたがコードをコミットする前に、自動的にチェックを実行することです。Gitの pre-commit 段階でコミットをインターセプトし、ESLint と Prettier を実行し、コードが規約に準拠している場合のみコミットを許可します。

lint-staged と組み合わせることで、Huskyはプロジェクト全体をスキャンするのではなく、変更されたファイルだけをチェックするため、非常に高速です。pre-commit フックが開発のテンポを遅くする心配はありません。

3つの連携の威力

これら3つのツールを組み合わせたワークフローは以下のようになります:

  1. ESLint がコード品質ルールを定義(例:var 禁止、const または let 必須)
  2. Prettier がコードフォーマットを統一(例:すべての文字列をシングルクォートに)
  3. Husky がコミット前に自動的にチェックを実行し、漏れがないことを保証

チームにとってのメリットは明らかです:

  • PRレビューでフォーマットの問題に悩まされず、ビジネスロジックに集中できる
  • コードのマージ競合が減少(フォーマットが統一されているため)
  • CIの失敗率が低下(コミット前にチェック済みのため)

完全な設定フロー

さて、実践編に入りましょう。このツールチェーンをステップバイステップで設定していきます。できるだけ落とし穴を避けるようにガイドします。

ステップ 1:Next.js プロジェクトの初期化

既にプロジェクトがある場合はスキップしてください。新規プロジェクトの場合は以下を実行します:

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

プロジェクト作成時、TypeScriptESLint を選択することを忘れないでください。Next.js 15 はデフォルトで ESLint を有効にしてくれるので、手間が省けます。

ステップ 2:依存関係のインストール

以下のコマンドを実行します(私は pnpm を使っていますが、npm や yarn でも構いません):

pnpm add -D eslint eslint-config-next prettier eslint-config-prettier husky lint-staged

各パッケージの役割を簡単に説明します:

  • eslint:ESLint コア
  • eslint-config-next:Next.js 公式 ESLint 設定(Next.js 特有のルールを含む)
  • prettier:Prettier コア
  • eslint-config-prettier:Prettier と競合する ESLint のフォーマットルールを無効化
  • husky:Git hooks 管理ツール
  • lint-staged:ステージングされた(コミット予定の)ファイルに対してのみチェックを実行

注意eslint-plugin-prettier はインストールしないでください。多くのチュートリアルがこれを推奨していますが、Prettier を ESLint ルールとして実行することになり、パフォーマンス問題を引き起こします。正しい方法は、ESLint と Prettier を別々に実行することです。

ステップ 3:ESLint の設定

ここは最もハマりやすいポイントです。特に Next.js 15 が ESLint 9 にアップグレードされてから、設定フォーマットが変わりました。

ESLint 9 の Flat Config フォーマットを使用(推奨)

プロジェクトのルートディレクトリに eslint.config.mjs を作成します:

// eslint.config.mjs
import { FlatCompat } from '@eslint/eslintrc';
import nextPlugin from '@next/eslint-plugin-next';

const compat = new FlatCompat();

export default [
  ...compat.extends('next/core-web-vitals'),
  {
    plugins: {
      '@next/next': nextPlugin,
    },
    rules: {
      '@next/next/no-img-element': 'error',
      'react/no-unescaped-entities': 'off',
      // ここに独自のルールを追加できます
    },
  },
  {
    ignores: ['.next/', 'node_modules/', 'out/'],
  },
];

重要ポイント

  • ESLint 9 は .eslintrc.json ではなく、flat config フォーマット(eslint.config.mjs)を使用します。
  • Next.js 15 にアップグレード後 “The Next.js plugin was not detected” エラーが出る場合、大抵は設定フォーマットが間違っています。
  • Next.js 16 では next lint コマンドが削除される予定なので、早めに新フォーマットに慣れておくのが賢明です。

ダウングレード案(互換性の問題がある場合)

一時的に flat config を使いたくない場合は、環境変数を設定して ESLint 8 の設定フォーマットにダウングレードできます:

ESLINT_USE_FLAT_CONFIG=false

その後、.eslintrc.json を使い続けます:

{
  "extends": ["next/core-web-vitals", "prettier"],
  "rules": {
    "@next/next/no-img-element": "error"
  }
}

とはいえ、これは将来のトレンドなので、できるだけ早めに flat config に移行することをお勧めします。

ステップ 4:Prettier の設定

プロジェクトルートに .prettierrc.json を作成します:

{
  "semi": true,
  "singleQuote": true,
  "trailingComma": "es5",
  "tabWidth": 2,
  "printWidth": 80,
  "arrowParens": "avoid"
}

これらは私の個人的なお気に入りの設定ですが、チームの習慣に合わせて調整してください:

  • singleQuote: true:シングルクォートの方がスッキリしていて好きです。
  • printWidth: 80:1行最大80文字。複数のエディタウィンドウを並べて表示するのに適しています。
  • trailingComma: 'es5':オブジェクトや配列の最後の項目の後にカンマを追加します。Git diff が綺麗になります。

次に .prettierignore を作成し、Prettier に無視させるファイルを指定します:

.next
out
node_modules
public
*.lock

VSCode 統合(推奨)

VSCode を使用している場合は、.vscode/settings.json を作成して、保存時に自動フォーマットするように設定できます:

{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

これで Ctrl + S を押してファイルを保存するたびに、Prettier が自動的にコードをフォーマットしてくれます。本当に快適です。

ステップ 5:Husky + lint-staged の設定

このステップが全設定プロセスの真髄であり、チームのコラボレーション効率を最も向上させる部分です。

Husky の初期化

以下を実行します:

pnpm dlx husky init

このコマンドは自動的に .husky/ フォルダを作成し、package.jsonprepare スクリプトを追加します:

{
  "scripts": {
    "prepare": "husky install"
  }
}

prepare スクリプトの役割は、チームメンバーが pnpm install を実行したときに、自動的に Husky hooks をインストールすることです。これにより、新しく参加した同僚も追加操作なしで、プロジェクトをクローンしたらすぐに自動チェックの保護を受けられます。

pre-commit hook の設定

.husky/pre-commit ファイルを編集します:

pnpm lint-staged

これだけです。毎回 git commit を実行すると、Husky はまず pnpm lint-staged を実行します。

lint-staged の設定

プロジェクトルートに .lintstagedrc.mjs を作成します:

export default {
  '*.{js,jsx,ts,tsx}': [
    'eslint --fix',
    'prettier --write',
  ],
  '*.{json,md,css}': [
    'prettier --write',
  ],
};

この設定の意味は:

  • .js, .jsx, .ts, .tsx ファイルに対しては、eslint --fix(問題の自動修正)を実行した後、prettier --write(フォーマット)を実行します。
  • .json, .md, .css ファイルに対しては、prettier --write だけを実行します。

パフォーマンス最適化のコツ

  1. ステージングされたファイルのみチェック:lint-staged は自動的に git add されたファイルをフィルタリングし、プロジェクト全体をスキャンしません。
  2. グローバルチェックを避ける:pre-commit 内で pnpm lint を実行してはいけません(全プロジェクトをチェックするため非常に遅いです)。
  3. テストをスキップ:pre-commit はフォーマットチェックと基本的なコード品質チェックのみを行い、複雑なテストは CI に任せます。
  4. 緊急時のスキップ:どうしてもチェックをスキップする必要がある場合(例:緊急のバグ修正)、git commit --no-verify を使用できます。

よくある問題のトラブルシューティング

Windows 環境で Husky が効かない

Windows を使用している場合、CMD や PowerShell ではなく Git Bash を使用していることを確認してください。また、.husky/pre-commit ファイルに実行権限があるか確認してください:

chmod +x .husky/pre-commit

フックの実行が遅すぎる

pre-commit フックが 10 秒以上かかる場合、lint-staged の設定を確認し、全プロジェクト検査を誤って設定していないか確認してください。通常、数ファイルだけの lint-staged は 2-3 秒で完了するはずです。

設定の検証

設定が完了したので、正しく動作するか検証してみましょう。

テスト手順

  1. 適当なファイルを変更し、わざとフォーマットの問題を作ります(例:シングルクォートをダブルクォートに変える、セミコロンを削除するなど)。
  2. git add . を実行。
  3. git commit -m "test" を実行。
  4. ターミナルの出力を観察します。

成功のサイン

設定が正しければ、以下のような出力が表示されます:

✔ Preparing lint-staged...
✔ Running tasks for staged files...
✔ Applying modifications from tasks...
✔ Cleaning up temporary files...

その後、変更したファイルを開くと、フォーマットの問題が自動的に修正されていることがわかります。これが自動化の魅力です。

失敗した場合

  • .husky/pre-commit ファイルが存在し、内容が正しいか確認してください。
  • .lintstagedrc.mjs ファイルがプロジェクトルートにあるか確認してください。
  • pnpm lint-staged を手動で実行して、エラーメッセージが出るか確認してください。

応用設定

基本的な設定でほとんどのニーズは満たせますが、より厳格なコード品質管理を求める場合は、以下の応用設定を検討してください。

commitlint の追加(コミットメッセージの標準化)

コードフォーマットだけでなく、コミットメッセージの標準も重要です。commitlint は、チームメンバーが統一されたコミットメッセージ形式(例:Conventional Commits)に従うことを保証します。

依存関係のインストール:

pnpm add -D @commitlint/cli @commitlint/config-conventional

commitlint.config.mjs を作成:

export default {
  extends: ['@commitlint/config-conventional'],
};

commit-msg hook を追加:

echo "pnpm commitlint --edit \$1" > .husky/commit-msg

これで、コミットメッセージが規範に合わない場合(例:git commit -m "fix bug" ではなく git commit -m "fix: bug")、コミットはブロックされます。

TypeScript 型チェックの追加

コミット前に TypeScript の型チェックを自動実行したい場合は、.lintstagedrc.mjs を修正します:

export default {
  '*.{ts,tsx}': [
    () => 'tsc --noEmit', // 型チェック
    'eslint --fix',
    'prettier --write',
  ],
  '*.{js,jsx}': [
    'eslint --fix',
    'prettier --write',
  ],
  '*.{json,md,css}': [
    'prettier --write',
  ],
};

注意tsc --noEmit はプロジェクト全体の型チェックを行うため、比較的遅いです。プロジェクトが大きい場合、pre-commit hook が遅くなる可能性があります。個人的には、型チェックは CI に任せ、pre-commit はフォーマットと基本チェックのみにすることをお勧めします。

Monorepo 設定

プロジェクトが Monorepo(pnpm workspace や Turborepo など)の場合、設定は少し複雑になります:

  • ルートディレクトリに Husky と lint-staged をインストール。
  • 各 package 下に個別の .lintstagedrc.mjs を作成。
  • 設定が他の package に「漏れない」ようにする。

具体的な設定については、lint-staged の公式ドキュメントを参照してください。

よくある質問と解決策

設定プロセス中にいくつかの問題に遭遇するかもしれません。ここでは一般的な落とし穴とその解決策をまとめます。

Q1: ESLint と Prettier のルールが競合したら?

症状:ESLint が特定の行のフォーマット不正を指摘するが、Prettier でフォーマットすると元に戻ってしまう。

解決策
eslint-config-prettier がインストールされていることを確認し、ESLint 設定で最後prettier を extends してください:

export default [
  ...compat.extends('next/core-web-vitals'),
  ...compat.extends('prettier'), // 最後に配置
];

eslint-config-prettier は Prettier と競合するすべての ESLint フォーマットルールを無効にし、Prettier がフォーマットに、ESLint がコード品質に集中できるようにします。

Q2: Next.js 15 アップグレード後、ESLint が “plugin not detected” エラーを吐く

症状pnpm lint 実行時にエラー:

Error: The Next.js plugin was not detected in your ESLint configuration.

解決策
これは通常、ESLint 9 の flat config 形式が正しくないためです。eslint.config.mjs@next/eslint-plugin-next を正しくインポートしているか確認してください:

import nextPlugin from '@next/eslint-plugin-next';

export default [
  {
    plugins: {
      '@next/next': nextPlugin,
    },
  },
];

どうしても解決しない場合は、一時的に ESLINT_USE_FLAT_CONFIG=false を設定して旧形式にダウングレードできます。

Q3: pre-commit hook が遅すぎる

症状:コミットのたびに10秒以上待たされ、開発効率に影響する。

解決策

  1. lint-staged がステージングされたファイルのみをチェックしているか確認(通常は自動)。
  2. pre-commit からテストスクリプトを削除(テストは CI で実行すべき)。
  3. プロジェクトが大きい場合、ESLint の実行を .ts.tsx ファイルのみに限定し、他は Prettier のみにする。

Q4: チームメンバーに Husky hooks がインストールされない

症状:新しい同僚がプロジェクトをクローンしたが、コミット時に pre-commit hook が作動しない。

解決策
package.jsonprepare スクリプトがあることを確認してください:

{
  "scripts": {
    "prepare": "husky install"
  }
}

同僚に一度 pnpm install を実行するように伝えてください。Husky hooks が自動的にインストールされます。

Q5: Windows 環境で Husky が効かない

症状:Windows ユーザーがコミットする際、pre-commit hook が実行されない。

解決策

  1. Git の設定が Git Bash を使用していることを確認(CMD ではなく)。
  2. .husky/pre-commit ファイルの権限を確認し、手動で実行権限を追加してみてください:
chmod +x .husky/pre-commit
  1. それでもダメな場合、Husky の再初期化を試してください:
rm -rf .husky
pnpm dlx husky init

まとめとベストプラクティス

このツールチェーンの設定には30分ほどかかりましたが、チームにもたらす価値は長期的です。

コアなメリット

  • コード品質向上:ESLint が開発段階で潜在的な問題を捕捉し、本番での事故を防ぐ。
  • チームコラボレーション効率化:統一されたコードフォーマットにより、無意味な PR 論争やマージ競合が減少。
  • 自動化による保証:Husky により、すべてのコミットが規範に準拠していることが保証され、チェック漏れの心配がなくなる。

ベストプラクティスの提案

  1. 段階的な設定:最初から厳しすぎるルールを設定しないこと。まずはデフォルト設定で運用し、問題が見つかったら徐々に調整する。
  2. チームの合意:Prettier の設定(シングルクォート vs ダブルクォートなど)は、独断ではなくチームメンバーと話し合って決める。
  3. パフォーマンス優先:pre-commit hook は必要なチェックのみを行い、複雑なテストは CI に任せる。
  4. 定期的な更新:Next.js と ESLint のバージョン変更に注意を払う。特に Next.js 16 では next lint コマンドが削除される予定です。

次のアクション

まだプロジェクトにこのツールチェーンを設定していないなら、今すぐ試してみることをお勧めします。この記事に従ってステップバイステップで操作すれば、30分で完了します。

そして、その設定をチームメンバーと共有し、全員の開発環境を統一しましょう。

最後に、チームの状況に合わせて Prettier と ESLint のルールを調整してください。ツールは人のためにあるものであり、ツールに振り回されないようにしましょう。

個人的な経験

正直なところ、このツールチェーンの設定は最初は面倒に感じるかもしれません。特に ESLint 9 の flat config 移行問題に直面した時は、私もかなり苦労しました。でも、一度使い始めたらもう手放せません。

今ではコードをコミットするたびに、フォーマットの問題を心配する必要も、lint の実行を忘れる心配もありません。pre-commit hook がすべて自動でチェックしてくれる安心感は素晴らしいです。

チームの PR レビュー効率も明らかに向上しました。以前は PR で「ここはシングルクォートにすべき」「インデントがおかしい」といった議論がありましたが、今では完全に消えました。Prettier が最初から統一してくれるからです。私たちはフォーマットの細部ではなく、ビジネスロジックやアーキテクチャ設計の議論に時間を使えるようになりました。

この自動化による効率向上は、設定にかかる時間を補って余りある価値があります。


この記事があなたの役に立つことを願っています。設定プロセスで問題が発生した場合は、コメント欄で教えてください。できる限りお答えします。

設定がうまくいきますように!

6 min read · 公開日: 2026年1月6日 · 更新日: 2026年1月22日

コメント

GitHubアカウントでログインしてコメントできます

関連記事