T-CREATOR

ESLint で Vue.js プロジェクトを守る設定ガイド

ESLint で Vue.js プロジェクトを守る設定ガイド

Vue.js プロジェクトの開発において、コードの品質を保つことは非常に重要です。特にチーム開発では、一貫性のあるコードスタイルと、潜在的なバグを事前に発見する仕組みが必要になります。この記事では、ESLint を使って Vue.js プロジェクトを効果的に管理し、開発チームの生産性を向上させる方法を段階的に解説していきます。

初心者の方でも理解できるよう、基本的な設定から実際の運用まで、具体的なコード例とともに詳しくご紹介します。また、実際の開発現場でよく遭遇するエラーとその解決方法も含めて、即座に活用できる実践的な内容となっています。

ESLint と Vue.js の関係性

ESLint が Vue.js プロジェクトにもたらすメリット

ESLint は、JavaScript のコード品質を保つためのリンターツールです。Vue.js プロジェクトで ESLint を活用することで、以下のような具体的なメリットが得られます。

#メリット具体的な効果
1コード品質の向上潜在的なバグや問題のあるコードパターンを事前に発見
2チーム開発の効率化統一されたコーディングスタイルでレビュー時間を短縮
3保守性の向上一貫したコード構造により、後から参加したメンバーも理解しやすい
4Vue.js 特有の問題回避テンプレート記法やリアクティブシステムでの誤用を防止

これらのメリットは、プロジェクトの規模が大きくなるほど、その効果を実感できるでしょう。

Vue.js 特有のコード品質課題

Vue.js プロジェクトでは、従来の JavaScript アプリケーションとは異なる特有の課題があります。

テンプレート構文での課題

Vue.js のテンプレート構文では、HTML と JavaScript が混在するため、以下のような問題が発生しやすくなります。

vue<template>
  <!-- 問題のあるコード例 -->
  <div v-if="user.name && user.age > 18">
    {{ user.name.toUpperCase() }}
  </div>
</template>

上記のコードでは、user.nameが空文字列の場合に意図しない動作をする可能性があります。

コンポーネント設計での課題

Vue.js コンポーネントでは、プロップスやイベントの定義が曖昧になりがちです。

vue<script>
export default {
  // 問題のあるコード例
  props: ['userData', 'config'],
  methods: {
    handleClick() {
      this.$emit('click', this.userData);
    },
  },
};
</script>

このような課題を解決するために、ESLint の Vue.js 専用ルールが効果的に機能します。

基本設定の構築

ESLint と Vue.js 用プラグインのインストール

まず、Vue.js プロジェクトで ESLint を使用するために必要なパッケージをインストールします。

bashyarn add -D eslint eslint-plugin-vue @vue/eslint-config-recommended

Vue 3 を使用している場合は、さらに以下のパッケージも追加します。

bashyarn add -D @vue/eslint-config-typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser

インストールが完了したら、パッケージの依存関係を確認しましょう。

bashyarn list --depth=0 | grep eslint

基本的な.eslintrc 設定ファイルの作成

プロジェクトのルートディレクトリに.eslintrc.jsファイルを作成します。

javascriptmodule.exports = {
  root: true,
  env: {
    node: true,
    browser: true,
    es2021: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:vue/vue3-essential',
  ],
  parserOptions: {
    ecmaVersion: 2021,
    sourceType: 'module',
  },
  rules: {
    // カスタムルールは後で追加
  },
};

この基本設定では、以下の要素を含んでいます:

  • root: true: このファイルを設定のルートとして扱う
  • env: 実行環境の指定(Node.js、ブラウザ、ES2021)
  • extends: 基本的な推奨ルールセットの継承
  • parserOptions: JavaScript の解析オプション

Vue.js 推奨ルールセットの適用

Vue.js プロジェクトでは、段階的にルールを適用することをお勧めします。以下の表に、各設定レベルの特徴をまとめました。

#設定レベル対象適用タイミング
1plugin:vue​/​vue3-essential基本的なエラー防止プロジェクト開始時
2plugin:vue​/​vue3-strongly-recommended可読性向上開発チームが慣れてから
3plugin:vue​/​vue3-recommended統一性とベストプラクティス本格運用時

まずはvue3-essentialから始めて、チームが慣れてきたら段階的に厳しいルールに移行しましょう。

javascript// 段階的な設定例
module.exports = {
  root: true,
  env: {
    node: true,
    browser: true,
    es2021: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:vue/vue3-essential', // 第1段階
    // 'plugin:vue/vue3-strongly-recommended', // 第2段階
    // 'plugin:vue/vue3-recommended' // 第3段階
  ],
  parserOptions: {
    ecmaVersion: 2021,
    sourceType: 'module',
  },
  rules: {
    'no-console':
      process.env.NODE_ENV === 'production'
        ? 'warn'
        : 'off',
    'no-debugger':
      process.env.NODE_ENV === 'production'
        ? 'warn'
        : 'off',
  },
};

Vue.js 特化ルールの活用

vue/recommended 設定の詳細

plugin:vue​/​vue3-recommendedを適用すると、以下のような Vue.js 特有のルールが有効になります。

主要なルールとその効果

javascript// .eslintrc.jsでの詳細設定例
module.exports = {
  extends: ['plugin:vue/vue3-recommended'],
  rules: {
    // コンポーネント名の規則
    'vue/component-name-in-template-casing': [
      'error',
      'PascalCase',
    ],

    // プロップス定義の強制
    'vue/require-prop-types': 'error',

    // 未使用変数の検出
    'vue/no-unused-vars': 'error',

    // テンプレート内での複数ルート要素の制御
    'vue/no-multiple-template-root': 'off', // Vue 3では許可

    // 属性の順序統一
    'vue/attributes-order': [
      'error',
      {
        order: [
          'DEFINITION',
          'LIST_RENDERING',
          'CONDITIONALS',
          'RENDER_MODIFIERS',
          'GLOBAL',
          'UNIQUE',
          'TWO_WAY_BINDING',
          'OTHER_DIRECTIVES',
          'OTHER_ATTR',
          'EVENTS',
          'CONTENT',
        ],
      },
    ],
  },
};

テンプレート構文でのルール適用

Vue.js テンプレートでよく発生するエラーとその対処法を見てみましょう。

エラー例 1: 未定義変数の使用

vue<template>
  <!-- エラー: 'userName' is not defined -->
  <div>{{ userName }}</div>
</template>

<script>
export default {
  data() {
    return {
      username: 'John', // 'userName'ではなく'username'
    };
  },
};
</script>

エラーメッセージ:

perl1:11  error  'userName' is not defined  vue/no-undef-properties

解決方法:

vue<template>
  <div>{{ username }}</div>
</template>

<script>
export default {
  data() {
    return {
      username: 'John',
    };
  },
};
</script>

エラー例 2: 不適切なディレクティブ使用

vue<template>
  <!-- エラー: v-forとv-ifの同時使用 -->
  <li
    v-for="item in items"
    v-if="item.active"
    :key="item.id"
  >
    {{ item.name }}
  </li>
</template>

エラーメッセージ:

perl2:5  error  This 'v-if' should be moved to the wrapper element  vue/no-use-v-if-with-v-for

解決方法:

vue<template>
  <template v-for="item in items" :key="item.id">
    <li v-if="item.active">
      {{ item.name }}
    </li>
  </template>
</template>

コンポーネント設計のためのルール

Vue.js コンポーネントの設計を改善するためのルール設定です。

javascript// .eslintrc.jsでのコンポーネント設計ルール
module.exports = {
  rules: {
    // プロップスのデフォルト値を強制
    'vue/require-default-prop': 'error',

    // イベント名のケースを統一
    'vue/custom-event-name-casing': ['error', 'kebab-case'],

    // コンポーネントの命名規則
    'vue/component-definition-name-casing': [
      'error',
      'PascalCase',
    ],

    // プロップスの型チェック強化
    'vue/prop-name-casing': ['error', 'camelCase'],

    // 不要なv-bindの検出
    'vue/no-useless-v-bind': 'error',
  },
};

良いコンポーネント設計の例:

vue<template>
  <div class="user-card">
    <h3>{{ userData.name }}</h3>
    <p>{{ userData.email }}</p>
    <button @click="handleEdit">編集</button>
  </div>
</template>

<script>
export default {
  name: 'UserCard',
  props: {
    userData: {
      type: Object,
      required: true,
      default: () => ({}),
    },
    editable: {
      type: Boolean,
      default: false,
    },
  },
  emits: ['edit-user'],
  methods: {
    handleEdit() {
      this.$emit('edit-user', this.userData.id);
    },
  },
};
</script>

TypeScript + Vue での設定強化

@typescript-eslint/parser との連携

TypeScript を使用する Vue.js プロジェクトでは、より厳密な型チェックと ESLint ルールの適用が可能になります。

javascript// .eslintrc.js(TypeScript対応版)
module.exports = {
  root: true,
  env: {
    node: true,
    browser: true,
    es2021: true,
  },
  extends: [
    'eslint:recommended',
    '@vue/typescript/recommended',
    'plugin:vue/vue3-recommended',
    '@vue/eslint-config-typescript',
  ],
  parser: 'vue-eslint-parser',
  parserOptions: {
    parser: '@typescript-eslint/parser',
    ecmaVersion: 2021,
    sourceType: 'module',
  },
  rules: {
    // TypeScript固有のルール
    '@typescript-eslint/no-explicit-any': 'warn',
    '@typescript-eslint/explicit-function-return-type':
      'off',
    '@typescript-eslint/no-unused-vars': 'error',
  },
};

Vue SFC での TypeScript 対応

Single File Component(SFC)で TypeScript を使用する場合の設定例です。

vue<template>
  <div class="todo-item">
    <input
      type="checkbox"
      :checked="todo.completed"
      @change="toggleTodo"
    />
    <span :class="{ completed: todo.completed }">
      {{ todo.text }}
    </span>
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue';

interface Todo {
  id: number;
  text: string;
  completed: boolean;
}

export default defineComponent({
  name: 'TodoItem',
  props: {
    todo: {
      type: Object as PropType<Todo>,
      required: true,
    },
  },
  emits: {
    'toggle-todo': (id: number) => typeof id === 'number',
  },
  methods: {
    toggleTodo(): void {
      this.$emit('toggle-todo', this.todo.id);
    },
  },
});
</script>

型安全性を高めるルール群

TypeScript と Vue.js を組み合わせた場合に有効なルール設定です。

javascriptmodule.exports = {
  rules: {
    // 型定義の強制
    '@typescript-eslint/explicit-module-boundary-types':
      'error',

    // any型の使用を制限
    '@typescript-eslint/no-explicit-any': 'error',

    // 未使用の変数を検出
    '@typescript-eslint/no-unused-vars': [
      'error',
      {
        argsIgnorePattern: '^_',
        varsIgnorePattern: '^_',
      },
    ],

    // Vue固有の型安全性ルール
    'vue/no-setup-props-destructure': 'error',
    'vue/component-api-style': ['error', ['script-setup']],

    // Composition APIでの型安全性
    'vue/no-ref-as-operand': 'error',
    'vue/no-watch-after-await': 'error',
  },
};

エラー例: プロップスの型定義不備

vue<!-- エラーが発生するコード -->
<script setup lang="ts">
// エラー: Props interface is missing
const props = defineProps(['message']);
</script>

エラーメッセージ:

lua3:15  error  Missing props type definition  @typescript-eslint/explicit-module-boundary-types

解決方法:

vue<script setup lang="ts">
interface Props {
  message: string;
  count?: number;
}

const props = defineProps<Props>();
</script>

実践的なワークフロー構築

VSCode との統合設定

開発効率を最大化するための VSCode 設定を構築しましょう。

.vscode/settings.json

json{
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
    "vue"
  ],
  "eslint.workingDirectories": ["."],
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "vetur.validation.template": false,
  "vetur.validation.script": false,
  "vetur.validation.style": false
}

.vscode/extensions.json

json{
  "recommendations": [
    "dbaeumer.vscode-eslint",
    "Vue.volar",
    "Vue.vscode-typescript-vue-plugin"
  ]
}

これらの設定により、保存時に自動的に ESLint ルールが適用され、開発体験が大幅に向上します。

Git Hooks での自動チェック

コミット前に自動的に ESLint チェックを実行する設定を行います。

lint-staged と husky のインストール

bashyarn add -D husky lint-staged

package.json の設定

json{
  "scripts": {
    "lint": "eslint --ext .js,.vue,.ts src/",
    "lint:fix": "eslint --ext .js,.vue,.ts src/ --fix",
    "prepare": "husky install"
  },
  "lint-staged": {
    "*.{js,vue,ts}": ["eslint --fix", "git add"]
  }
}

pre-commit フックの設定

bashnpx husky add .husky/pre-commit "npx lint-staged"

この設定により、問題のあるコードはコミットされることなく、チーム全体のコード品質が保たれます。

CI/CD パイプラインでの品質管理

GitHub Actions を使用した CI/CD パイプラインでの ESLint チェック設定例です。

.github/workflows/ci.yml

yamlname: CI

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

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'yarn'

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

      - name: Run ESLint
        run: yarn lint

      - name: Run ESLint with output
        run: yarn lint --format=json --output-file=eslint-report.json
        continue-on-error: true

      - name: Upload ESLint report
        uses: actions/upload-artifact@v3
        if: always()
        with:
          name: eslint-report
          path: eslint-report.json

トラブルシューティング

よくあるエラーと解決方法

エラー 1: Parser 設定関連

go✗ Parsing error: Unexpected token <

原因: Vue SFC ファイルのパーサー設定が不適切

解決方法:

javascript// .eslintrc.js
module.exports = {
  parser: 'vue-eslint-parser',
  parserOptions: {
    parser: '@typescript-eslint/parser', // TypeScript使用時
    ecmaVersion: 2021,
    sourceType: 'module',
  },
};

エラー 2: プラグイン依存関係

arduino✗ ESLint couldn't find the plugin "eslint-plugin-vue"

原因: 必要なプラグインがインストールされていない

解決方法:

bashyarn add -D eslint-plugin-vue

エラー 3: 設定ファイルの競合

csharp✗ ESLint configuration in .eslintrc.js is invalid

原因: 複数の設定ファイルが競合している

解決方法:

  • .eslintrc.js以外の設定ファイル(.eslintrc.jsonなど)を削除
  • package.json内のeslintConfig設定を削除

エラー 4: Vue 3 Composition API 関連

perl'ref' is not defined  no-undef

原因: Composition API の自動インポート設定不備

解決方法:

javascript// .eslintrc.js
module.exports = {
  globals: {
    defineProps: 'readonly',
    defineEmits: 'readonly',
    defineExpose: 'readonly',
    withDefaults: 'readonly',
  },
};

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

大規模プロジェクトで ESLint のパフォーマンスを向上させる方法です。

1. キャッシュの活用

bash# .eslintcacheファイルを利用
yarn lint --cache --cache-location .eslintcache

2. 並列処理の活用

json{
  "scripts": {
    "lint": "eslint --ext .js,.vue,.ts src/ --max-warnings 0 --cache"
  }
}

3. 不要なファイルの除外

javascript// .eslintrc.js
module.exports = {
  ignorePatterns: [
    'dist/',
    'node_modules/',
    '*.d.ts',
    'public/',
    '.nuxt/',
    'coverage/',
  ],
};

4. ルールの最適化

javascriptmodule.exports = {
  rules: {
    // 重いルールを無効化または調整
    'import/no-cycle': 'off', // 循環依存チェックは重い
    'vue/no-unused-components': 'warn', // エラーではなく警告に
  },
};

まとめ

ESLint を Vue.js プロジェクトに導入することで、コードの品質向上とチーム開発の効率化を実現できます。この記事で解説した内容を段階的に適用することで、以下の効果が期待できます。

#効果具体的な改善点
1開発速度の向上自動修正機能により手動修正時間を削減
2バグの早期発見実行前に潜在的な問題を検出
3コードレビューの効率化スタイルの統一によりレビュー時間を短縮
4新人教育のサポートベストプラクティスを自動的に学習

重要なのは、一度にすべてのルールを適用するのではなく、チームの成熟度に合わせて段階的に導入することです。まずは基本的な設定から始めて、徐々に厳密なルールへと移行していきましょう。

また、エラーが発生した際は、この記事のトラブルシューティングセクションを参考に、適切な対処を行ってください。継続的な改善により、より良い開発環境を構築できるはずです。

関連リンク