T-CREATOR

Prettier と ESLint の違いと併用パターン

Prettier と ESLint の違いと併用パターン

現代の JavaScript・TypeScript 開発において、コードの品質と一貫性を保つことは、プロジェクトの成功に直結する重要な要素です。特にチーム開発では、開発者それぞれが異なるコーディングスタイルを持っているため、統一されたコード品質の維持が大きな課題となります。

そこで登場するのが、Prettier と ESLint という 2 つの強力なツールです。これらのツールを適切に使い分け、効果的に併用することで、コードレビューの時間短縮、バグの早期発見、そして開発効率の大幅な向上を実現できるでしょう。

しかし、「Prettier と ESLint の違いがよくわからない」「どちらを使えばいいの?」「併用する際の設定が複雑で困っている」といった声をよく耳にします。今回は、これらの疑問を解消し、実際のプロジェクトで即座に活用できる実践的な知識をお届けいたします。基本概念から始まり、具体的な設定方法、そして開発ワークフローへの統合まで、段階的に理解を深めていきましょう。

Prettier と ESLint の基本概念

Prettier の役割と特徴

Prettier は、コードフォーマッターとして位置づけられるツールです。主な目的は、コードの見た目を統一し、読みやすく美しい形に自動整形することにあります。

Prettier の核となる特徴は以下の通りです。

#特徴説明メリット
1自動整形コードを保存時に自動的に整形手動作業の削減
2意見の統一設定項目を最小限に抑制チーム内での議論回避
3多言語対応JavaScript、TypeScript、CSS、HTML など統一的な開発体験
4エディタ統合主要なエディタで直接利用可能シームレスな開発フロー
5設定の簡素化最小限の設定で最大の効果導入コストの削減

Prettier の哲学は「設定より規約」にあります。細かな設定項目を排除し、合理的なデフォルト設定を提供することで、開発者がフォーマットについて悩む時間を最小限に抑えているのです。

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

上記のような最小限の設定で、一貫性のあるコードフォーマットを実現できます。

ESLint の役割と特徴

一方、ESLint は**静的解析ツール(リンター)**として機能します。コードの品質向上、潜在的なバグの検出、コーディング規約の遵守を主な目的としています。

ESLint の主要な機能は以下のような多岐にわたります。

#機能カテゴリ具体例効果
1構文エラー検出セミコロン忘れ、括弧の不一致バグの早期発見
2ベストプラクティス強制===の使用、varの禁止コード品質向上
3スタイル統一インデント、命名規則可読性向上
4セキュリティチェックevalの使用警告セキュリティ強化
5カスタムルールプロジェクト固有の制約柔軟な品質管理

ESLint の強みは、その高度な設定可能性にあります。プロジェクトの要件に応じて、細かくルールをカスタマイズできるため、チームの開発方針に合わせた品質管理が可能です。

javascriptmodule.exports = {
  extends: [
    'eslint:recommended',
    '@typescript-eslint/recommended',
  ],
  rules: {
    'no-console': 'warn',
    'prefer-const': 'error',
    '@typescript-eslint/no-unused-vars': 'error',
    'no-multiple-empty-lines': ['error', { max: 2 }],
  },
};

このように、ESLint では個別のルールを細かく設定し、プロジェクトに最適な品質基準を構築できるのです。

両者の基本的な違い

Prettier と ESLint の違いを明確に理解するために、以下の観点から比較してみましょう。

typescript// 元のコード(品質・フォーマット共に問題あり)
function calculateTotal(items) {
  let total = 0;
  for (var i = 0; i < items.length; i++) {
    if (items[i].price != null) {
      total += items[i].price;
    }
  }
  return total;
}

// ESLintが指摘する問題
// - var の使用(let/const を推奨)
// - != の使用(!== を推奨)
// - セミコロンの不統一

// Prettierが修正する問題
// - インデントの統一
// - スペースの調整
// - セミコロンの統一

つまり、ESLint は「何が問題か」を教えてくれ、Prettier は「どう見せるか」を整えてくれるのです。

機能比較と使い分けの判断基準

フォーマッターとリンターの境界線

Prettier と ESLint の機能には、一部重複する領域があります。この境界線を正しく理解することで、適切な使い分けが可能になります。

Prettier の専門領域

Prettier が専門的に扱う領域は、純粋に「見た目」に関わる部分です。

typescript// Prettierが処理する内容の例

// インデントの統一
if (condition) {
  return true; // 不適切なインデント
}

// ↓ Prettierが自動修正

if (condition) {
  return true; // 適切なインデント
}

// 行の長さの調整
const longVariableName = someFunction(
  parameter1,
  parameter2,
  parameter3,
  parameter4
);

// ↓ Prettierが自動修正

const longVariableName = someFunction(
  parameter1,
  parameter2,
  parameter3,
  parameter4
);

// 引用符の統一
const message = 'Hello, world!';
const greeting = 'Hi there!';

// ↓ Prettierが自動修正(singleQuote: true の場合)

const message = 'Hello, world!';
const greeting = 'Hi there!';

ESLint の専門領域

ESLint が専門的に扱うのは、コードの「品質」や「正確性」に関わる部分です。

typescript// ESLintが検出・修正する内容の例

// 潜在的なバグの検出
function findUser(users, id) {
  for (var i = 0; i < users.length; i++) {
    // var の使用を警告
    if (users[i].id == id) {
      // == の使用を警告(=== を推奨)
      return users[i];
    }
  }
}

// ベストプラクティスの強制
const data = [1, 2, 3];
data.map((item) => {
  console.log(item); // 副作用を持つ処理でmapを使用(forEachを推奨)
});

// 未使用変数の検出
const unusedVariable = 'This is not used'; // 未使用変数を警告
const usedVariable = 'This is used';
console.log(usedVariable);

重複する領域の対処法

一部の機能は両者で重複しています。例えば、セミコロンの有無やインデントの設定などです。

typescript// 重複する領域の例

// セミコロンの扱い
const example = 'Hello'; // セミコロンなし

// Prettierの設定: "semi": true
// ESLintの設定: "semi": ["error", "always"]
// 両方ともセミコロンを要求する場合

この重複を解決するため、後述する併用パターンでは、適切な設定の優先順位を決める必要があります。

使い分けの判断基準

プロジェクトの性質や要件に応じて、適切な使い分けを行うための判断基準をご紹介します。

プロジェクト規模による判断

プロジェクト規模推奨構成理由
個人プロジェクトPrettier のみ簡単な設定で即座に効果を実感
小規模チームPrettier + 基本的な ESLintバランスの取れた品質管理
中規模チームPrettier + カスタマイズ ESLintチーム固有のルール設定
大規模チームPrettier + 厳格な ESLint統一された高品質コード

開発フェーズによる判断

typescript// プロトタイピング段階
// Prettierのみで十分、素早い開発を優先

// 開発初期段階
// Prettier + 基本的なESLintで品質の土台を構築

// 開発中期段階
// カスタムルールを追加して、プロジェクト固有の品質基準を確立

// リリース前段階
// 厳格なESLint設定で最終的な品質チェック

技術スタックによる判断

json{
  "JavaScript のみ": {
    "推奨": "Prettier + ESLint (JavaScript)",
    "設定": "標準的な設定で十分"
  },
  "TypeScript": {
    "推奨": "Prettier + ESLint (TypeScript)",
    "設定": "型安全性を重視したルール"
  },
  "React": {
    "推奨": "Prettier + ESLint (React)",
    "設定": "React固有のルールを追加"
  },
  "Node.js": {
    "推奨": "Prettier + ESLint (Node.js)",
    "設定": "サーバーサイド固有のルール"
  }
}

基本的な導入と設定方法

Prettier の導入と設定

まず、Prettier の基本的な導入手順から始めましょう。

インストール

bash# 開発依存関係としてインストール
yarn add --dev prettier

# グローバルインストール(オプション)
yarn global add prettier

基本設定ファイルの作成

プロジェクトルートに .prettierrc ファイルを作成します。

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

無視ファイルの設定

.prettierignore ファイルを作成し、フォーマット対象外のファイルを指定します。

ignore# 依存関係
node_modules/
yarn.lock

# ビルド成果物
dist/
build/
public/

# 設定ファイル
.env
.env.local

# その他
*.min.js
*.min.css

package.json スクリプトの設定

json{
  "scripts": {
    "format": "prettier --write .",
    "format:check": "prettier --check .",
    "format:staged": "prettier --write --staged"
  }
}

ESLint の導入と設定

次に、ESLint の基本的な導入手順をご紹介します。

インストール

bash# 基本的なESLintのインストール
yarn add --dev eslint

# TypeScriptプロジェクトの場合
yarn add --dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin

# Reactプロジェクトの場合
yarn add --dev eslint-plugin-react eslint-plugin-react-hooks

初期設定の生成

bash# 対話形式で初期設定を生成
yarn eslint --init

基本設定ファイルの例

.eslintrc.js ファイルの例をご紹介します。

javascriptmodule.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
  },
  extends: [
    'eslint:recommended',
    '@typescript-eslint/recommended',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
  },
  plugins: ['@typescript-eslint'],
  rules: {
    // エラーレベルの設定
    'no-console': 'warn',
    'no-debugger': 'error',
    'prefer-const': 'error',

    // TypeScript固有のルール
    '@typescript-eslint/no-unused-vars': 'error',
    '@typescript-eslint/explicit-function-return-type':
      'warn',

    // スタイルに関するルール(Prettierと併用時は注意)
    indent: ['error', 2],
    quotes: ['error', 'single'],
    semi: ['error', 'always'],
  },
};

無視ファイルの設定

.eslintignore ファイルを作成します。

ignore# 依存関係
node_modules/

# ビルド成果物
dist/
build/

# 設定ファイル
*.config.js
.prettierrc.js

# テスト設定
jest.config.js

package.json スクリプトの設定

json{
  "scripts": {
    "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
    "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
    "lint:check": "eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 0"
  }
}

設定の動作確認

導入後は、実際に動作確認を行いましょう。

typescript// test.ts(テスト用ファイル)
function example() {
  var message = 'Hello, world!';
  console.log(message);
}

// ESLintの実行
// yarn lint
// → var の使用、セミコロンの不統一などを指摘

// Prettierの実行
// yarn format
// → インデント、セミコロンの統一などを自動修正

この段階で、それぞれのツールが正しく動作することを確認できます。

併用時の設定パターン

競合回避の基本原則

Prettier と ESLint を併用する際の最も重要なポイントは、役割分担の明確化です。両者が同じ項目について異なる判断を下すと、無限ループのような状況が発生する可能性があります。

基本的な競合回避戦略

  1. Prettier がフォーマットを担当
  2. ESLint がコード品質を担当
  3. 重複する部分は Prettier を優先

この原則に基づいて、具体的な設定パターンを構築していきます。

パターン 1:eslint-config-prettier を使用した設定

最も一般的で推奨される併用パターンです。

bash# 必要なパッケージのインストール
yarn add --dev eslint-config-prettier

.eslintrc.js の設定を更新します。

javascriptmodule.exports = {
  extends: [
    'eslint:recommended',
    '@typescript-eslint/recommended',
    'prettier', // これを最後に追加(重要)
  ],
  parser: '@typescript-eslint/parser',
  plugins: ['@typescript-eslint'],
  rules: {
    // フォーマットに関するルールは除外
    // 'indent': 'off',  // Prettierに任せる
    // 'quotes': 'off',  // Prettierに任せる
    // 'semi': 'off',    // Prettierに任せる

    // コード品質に関するルールのみ設定
    'no-console': 'warn',
    'no-debugger': 'error',
    'prefer-const': 'error',
    'no-var': 'error',
    '@typescript-eslint/no-unused-vars': 'error',
  },
};

パターン 2:eslint-plugin-prettier を使用した統合

ESLint の中で Prettier を実行するパターンです。

bash# 必要なパッケージのインストール
yarn add --dev eslint-plugin-prettier eslint-config-prettier

.eslintrc.js の設定:

javascriptmodule.exports = {
  extends: [
    'eslint:recommended',
    '@typescript-eslint/recommended',
    'plugin:prettier/recommended', // これ一つで統合
  ],
  parser: '@typescript-eslint/parser',
  plugins: ['@typescript-eslint'],
  rules: {
    // Prettierのルール違反もESLintエラーとして表示
    'prettier/prettier': 'error',

    // その他のルール
    'no-console': 'warn',
    'prefer-const': 'error',
  },
};

パターン 3:カスタム設定による高度な制御

プロジェクト固有の要件に応じた詳細な設定パターンです。

javascript// .eslintrc.js
module.exports = {
  extends: [
    'eslint:recommended',
    '@typescript-eslint/recommended',
    'prettier',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 2021,
    sourceType: 'module',
    project: './tsconfig.json',
  },
  plugins: ['@typescript-eslint'],
  rules: {
    // 厳格な型チェック
    '@typescript-eslint/strict-boolean-expressions':
      'error',
    '@typescript-eslint/prefer-nullish-coalescing': 'error',
    '@typescript-eslint/prefer-optional-chain': 'error',

    // セキュリティ関連
    'no-eval': 'error',
    'no-implied-eval': 'error',
    'no-new-func': 'error',

    // パフォーマンス関連
    'no-loop-func': 'error',
    'no-inner-declarations': 'error',

    // 保守性向上
    'max-complexity': ['error', 10],
    'max-depth': ['error', 4],
    'max-lines-per-function': ['error', 50],
  },
  overrides: [
    {
      // テストファイル用の設定
      files: ['**/*.test.ts', '**/*.spec.ts'],
      rules: {
        'no-console': 'off',
        '@typescript-eslint/no-explicit-any': 'off',
      },
    },
  ],
};

設定ファイルの統合管理

複数の設定ファイルを効率的に管理する方法をご紹介します。

json// package.json
{
  "prettier": {
    "semi": true,
    "singleQuote": true,
    "tabWidth": 2,
    "trailingComma": "es5",
    "printWidth": 80
  },
  "eslintConfig": {
    "extends": ["eslint:recommended", "prettier"],
    "rules": {
      "no-console": "warn"
    }
  }
}

あるいは、専用の設定ファイルを作成する方法もあります。

javascript// prettier.config.js
module.exports = {
  semi: true,
  singleQuote: true,
  tabWidth: 2,
  trailingComma: 'es5',
  printWidth: 80,
  useTabs: false,
  bracketSpacing: true,
  arrowParens: 'avoid',
  endOfLine: 'lf',
};

設定の妥当性確認

設定が正しく動作することを確認するためのテスト方法です。

typescript// test-config.ts(設定テスト用ファイル)
function testFunction() {
  var message = 'Hello, world!';
  let unused = 'unused variable';
  console.log(message);
  if (true == true) {
    return message;
  }
}

// 期待される動作:
// 1. Prettier: フォーマットの自動修正
// 2. ESLint: var使用、未使用変数、== 使用の警告

実行コマンド:

bash# 1. ESLintチェック
yarn lint test-config.ts

# 2. Prettierフォーマット
yarn format test-config.ts

# 3. 再度ESLintチェック(フォーマット後)
yarn lint test-config.ts

この手順により、設定の競合がないことを確認できます。

開発ワークフローへの統合

エディタ統合による自動化

Visual Studio Code での設定

VS Code での効率的な統合方法をご紹介します。

.vscode​/​settings.json ファイルを作成:

json{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
    "source.organizeImports": true
  },
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact"
  ],
  "prettier.requireConfig": true,
  "typescript.preferences.importModuleSpecifier": "relative"
}

拡張機能の推奨設定 .vscode​/​extensions.json

json{
  "recommendations": [
    "esbenp.prettier-vscode",
    "dbaeumer.vscode-eslint",
    "@typescript-eslint.typescript-eslint",
    "ms-vscode.vscode-typescript-next"
  ]
}

WebStorm での設定

WebStorm での設定手順:

  1. SettingsLanguages & FrameworksJavaScriptPrettier
  2. Prettier package でローカルインストールを選択
  3. Run for files で対象ファイルを指定
  4. On code reformatOn save を有効化

ESLint 設定:

  1. SettingsLanguages & FrameworksJavaScriptCode Quality ToolsESLint
  2. Automatic ESLint configuration を有効化
  3. Run eslint --fix on save を有効化

Git フックとの統合

Husky と lint-staged の設定

コミット時の自動チェックを設定します。

bash# 必要なパッケージのインストール
yarn add --dev husky lint-staged

package.json の設定:

json{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
      "pre-push": "yarn lint:check"
    }
  },
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": [
      "eslint --fix",
      "prettier --write"
    ],
    "*.{json,css,md}": ["prettier --write"]
  }
}

Husky の初期化

bash# Huskyの初期化
yarn husky install

# pre-commitフックの追加
yarn husky add .husky/pre-commit "yarn lint-staged"

# pre-pushフックの追加
yarn husky add .husky/pre-push "yarn lint:check"

CI/CD パイプラインでの品質チェック

GitHub Actions での設定

.github​/​workflows​/​quality-check.yml

yamlname: Code Quality Check

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

jobs:
  quality-check:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [16.x, 18.x]

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'yarn'

      - name: Install dependencies
        run: yarn install --frozen-lockfile

      - name: Run Prettier check
        run: yarn format:check

      - name: Run ESLint
        run: yarn lint:check

      - name: Run type check
        run: yarn type-check

      - name: Run tests
        run: yarn test

並列実行による高速化

yamljobs:
  format-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'yarn'
      - run: yarn install --frozen-lockfile
      - run: yarn format:check

  lint-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'yarn'
      - run: yarn install --frozen-lockfile
      - run: yarn lint:check

開発効率を向上させるスクリプト

package.json の総合的なスクリプト設定:

json{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",

    "format": "prettier --write .",
    "format:check": "prettier --check .",

    "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
    "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
    "lint:check": "eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 0",

    "type-check": "tsc --noEmit",

    "quality": "yarn format && yarn lint:fix && yarn type-check",
    "quality:check": "yarn format:check && yarn lint:check && yarn type-check",

    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage",

    "prepare": "husky install"
  }
}

段階的な品質向上戦略

既存プロジェクトへの導入を段階的に行う方法:

フェーズ 1:基本導入(1 週間)

bash# 1. Prettierの導入
yarn add --dev prettier
# 基本設定ファイルの作成
# エディタ統合の設定

# 2. 全ファイルのフォーマット
yarn format

# 3. Git コミット
git add .
git commit -m "feat: add Prettier formatting"

フェーズ 2:基本的な ESLint 導入(1 週間)

bash# 1. ESLintの導入
yarn add --dev eslint eslint-config-prettier

# 2. 基本設定の作成
yarn eslint --init

# 3. 段階的な修正
yarn lint:fix

フェーズ 3:高度な設定とワークフロー統合(2 週間)

bash# 1. 高度な設定の追加
# TypeScript、React固有のルール

# 2. CI/CD統合
# GitHub Actions設定

# 3. Git フック設定
yarn add --dev husky lint-staged
yarn husky install

この段階的アプローチにより、チームへの負担を最小限に抑えながら、品質向上を実現できます。

まとめ

Prettier と ESLint の適切な使い分けと併用により、開発効率と品質の両立を実現できることをご理解いただけたでしょうか。今回ご紹介した内容を振り返りながら、最適な開発環境構築のポイントをまとめてみましょう。

まず、基本概念の理解が重要です。Prettier は「見た目の統一」、ESLint は「品質の向上」という明確な役割分担を理解することで、適切な設定と運用が可能になります。これらのツールは競合するものではなく、相互に補完し合う関係にあるのです。

機能比較と使い分けについては、プロジェクトの規模、開発フェーズ、技術スタックに応じて最適な組み合わせを選択することが大切です。個人プロジェクトでは Prettier のみで十分な場合もありますが、チーム開発では両者の併用が効果的でしょう。

導入と設定の段階では、段階的なアプローチを取ることをお勧めします。まず基本的な設定から始めて、プロジェクトの成熟度に応じて徐々に高度な設定を追加していくことで、チームの負担を最小限に抑えながら品質向上を実現できます。

併用設定のパターンでは、eslint-config-prettierを使用した競合回避が最も実用的です。この設定により、両者の強みを活かしながら、設定の複雑さを抑えることができるでしょう。

そして開発ワークフローへの統合により、手動での品質チェックを自動化し、開発者がコードの本質的な部分に集中できる環境を構築できます。エディタ統合、Git フック、CI/CD パイプラインの設定により、品質管理が自然な開発フローの一部となるのです。

これらのツールの導入は、短期的には設定の学習コストが発生しますが、中長期的には開発効率の大幅な向上をもたらします。コードレビューの時間短縮、バグの早期発見、チーム内でのコーディングスタイルの統一など、その効果は多岐にわたるでしょう。

皆様のプロジェクトでも、今回ご紹介した設定パターンを参考に、最適な開発環境を構築していただければ幸いです。品質の高いコードを効率的に開発し、ユーザーに価値を提供し続けることができる環境作りの一助となれば嬉しく思います。

関連リンク