T-CREATOR

ESLint で import 順序を自動で整える方法

ESLint で import 順序を自動で整える方法

コードの可読性向上において、import 文の順序は意外と重要な要素です。しかし、手動で管理するのは煩雑で、チーム開発では統一が困難になりがちですよね。ESLint の import 順序管理機能を活用することで、この問題を根本的に解決できます。

この記事では、eslint-plugin-import を使った import 順序の自動整理方法を、実際のエラー例とともに詳しく解説していきます。設定から実践まで、段階的にマスターしていきましょう。

import 順序管理の重要性

なぜ import 順序が重要なのか

import 文の順序が統一されていないプロジェクトでは、以下のような問題が発生します:

#問題具体例影響度
1可読性の低下関連するモジュールが離れて配置
2依存関係の把握困難外部・内部ライブラリが混在
3コードレビューの負担順序の違いによる差分の増加
4開発効率の低下必要なモジュールを探す時間

実際の問題のあるコード例を見てみましょう:

javascript// 問題のある import 順序
import { Button } from './components/Button';
import React from 'react';
import { API_ENDPOINTS } from '../config/api';
import lodash from 'lodash';
import { formatDate } from './utils/date';
import axios from 'axios';

このような順序では、どこに何があるか把握しにくく、新しい import を追加する際にも迷ってしまいます。

理想的な import 順序の原則

一般的に推奨される import 順序は以下の通りです:

javascript// 1. Node.js 標準モジュール
import fs from 'fs';
import path from 'path';

// 2. 外部ライブラリ(npm パッケージ)
import React from 'react';
import axios from 'axios';
import lodash from 'lodash';

// 3. 内部モジュール(相対パス以外)
import { API_ENDPOINTS } from 'config/api';
import { formatDate } from 'utils/date';

// 4. 相対パスでの内部モジュール
import { Button } from './components/Button';
import { Modal } from '../components/Modal';

この順序により、依存関係が明確になり、コードの構造が理解しやすくなります。

eslint-plugin-import の基本設定

プラグインのインストール

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

bash# eslint-plugin-import のインストール
yarn add --dev eslint-plugin-import

# TypeScript を使用する場合の追加パッケージ
yarn add --dev @typescript-eslint/parser

インストール後、ESLint 設定ファイルにプラグインを追加します。

基本的な設定ファイル

.eslintrc.js での基本設定例:

javascriptmodule.exports = {
  extends: ['eslint:recommended'],
  plugins: ['import'],
  rules: {
    // import 順序の基本ルール
    'import/order': 'error',
  },
  settings: {
    // import 解決の設定
    'import/resolver': {
      node: {
        extensions: ['.js', '.jsx', '.ts', '.tsx'],
      },
    },
  },
};

TypeScript プロジェクトの場合は、より詳細な設定が必要です:

javascriptmodule.exports = {
  parser: '@typescript-eslint/parser',
  extends: [
    'eslint:recommended',
    '@typescript-eslint/recommended',
  ],
  plugins: ['@typescript-eslint', 'import'],
  rules: {
    'import/order': 'error',
  },
  settings: {
    'import/resolver': {
      typescript: {
        alwaysTryTypes: true,
        project: './tsconfig.json',
      },
    },
  },
};

設定の動作確認

設定が正しく動作するか確認してみましょう:

bash# ESLint の実行
yarn lint

# 自動修正付きの実行
yarn lint --fix

正しく設定されている場合、import 順序の問題があるファイルで以下のようなエラーが表示されます:

goerror: `react` import should occur before import of `./components/Button` (import/order)

主要なルール設定と効果

import/order ルールの詳細設定

import​/​order ルールは、非常に柔軟な設定が可能です。詳細な設定例をご紹介します:

javascriptmodule.exports = {
  rules: {
    'import/order': [
      'error',
      {
        // グループの定義
        groups: [
          'builtin', // Node.js 標準モジュール
          'external', // npm パッケージ
          'internal', // 内部モジュール
          'parent', // 親ディレクトリ
          'sibling', // 同階層
          'index', // index ファイル
        ],
        // グループ間の改行
        'newlines-between': 'always',
        // アルファベット順のソート
        alphabetize: {
          order: 'asc',
          caseInsensitive: true,
        },
        // パスグループの詳細設定
        pathGroups: [
          {
            pattern: 'react',
            group: 'external',
            position: 'before',
          },
          {
            pattern: '@/**',
            group: 'internal',
            position: 'before',
          },
        ],
        pathGroupsExcludedImportTypes: ['builtin'],
      },
    ],
  },
};

実際のエラーパターンとその解決

よく遭遇するエラーパターンを見てみましょう:

エラー 1: 順序違反

javascript// エラーが発生するコード
import { Button } from './Button';
import React from 'react';
go1:1  error  `react` import should occur before import of `./Button`  import/order

解決方法: React を先頭に移動

javascript// 修正後
import React from 'react';
import { Button } from './Button';

エラー 2: グループ間の改行不足

javascript// エラーが発生するコード
import React from 'react';
import { Button } from './Button';
sql2:1  error  There should be at least one empty line between import groups  import/order

解決方法: グループ間に改行を追加

javascript// 修正後
import React from 'react';

import { Button } from './Button';

エラー 3: アルファベット順序違反

javascript// エラーが発生するコード
import { useState } from 'react';
import { Button } from 'antd';
go2:1  error  `antd` import should occur before import of `react`  import/order

解決方法: アルファベット順に整列

javascript// 修正後
import { Button } from 'antd';
import { useState } from 'react';

高度なルール設定

プロジェクトの要求に応じて、より詳細な設定も可能です:

javascript'import/order': [
  'error',
  {
    groups: [
      'builtin',
      'external',
      'internal',
      ['parent', 'sibling'],
      'index',
    ],
    'newlines-between': 'always',
    alphabetize: {
      order: 'asc',
      caseInsensitive: true,
    },
    // カスタムパスグループ
    pathGroups: [
      // React 関連を最優先
      {
        pattern: 'react**',
        group: 'external',
        position: 'before',
      },
      // UI ライブラリを React の後
      {
        pattern: '@mui/**',
        group: 'external',
        position: 'after',
      },
      // プロジェクト内のコンポーネント
      {
        pattern: '@/components/**',
        group: 'internal',
        position: 'before',
      },
      // ユーティリティ関数
      {
        pattern: '@/utils/**',
        group: 'internal',
        position: 'after',
      },
    ],
    pathGroupsExcludedImportTypes: ['react'],
  },
],

自動修正機能の活用

--fix オプションの使用

ESLint の自動修正機能を使用することで、import 順序を自動的に整理できます:

bash# 単一ファイルの修正
yarn eslint src/components/Button.tsx --fix

# プロジェクト全体の修正
yarn eslint src/ --fix

# 特定の拡張子のみ修正
yarn eslint "src/**/*.{ts,tsx}" --fix

package.json での自動修正スクリプト

便利なスクリプトを package.json に追加しましょう:

json{
  "scripts": {
    "lint": "eslint src/",
    "lint:fix": "eslint src/ --fix",
    "lint:imports": "eslint src/ --fix --rule 'import/order: error'",
    "format:imports": "eslint src/ --fix --rule 'import/order: [error, {groups: [\"builtin\", \"external\", \"internal\", \"parent\", \"sibling\"], \"newlines-between\": \"always\", alphabetize: {order: \"asc\"}}]'"
  }
}

段階的な修正アプローチ

大規模プロジェクトでは、段階的に修正することをお勧めします:

bash# 1. まず警告レベルで確認
yarn eslint src/ --rule 'import/order: warn'

# 2. 特定のディレクトリから開始
yarn eslint src/components/ --fix

# 3. 徐々に範囲を拡大
yarn eslint src/ --fix

修正前後の差分を確認することも重要です:

bash# Git で差分を確認
git diff

# 修正内容が適切か確認してからコミット
git add .
git commit -m "fix: import order with eslint-plugin-import"

エディタ連携設定

VS Code での設定

VS Code で ESLint の自動修正を有効にする設定例:

json// .vscode/settings.json
{
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "editor.formatOnSave": true,
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact"
  ],
  "eslint.workingDirectories": ["./"],
  "typescript.preferences.organizeImports": false
}

重要なのは "typescript.preferences.organizeImports": false の設定です。これにより、TypeScript の標準機能ではなく ESLint の import 順序ルールが優先されます。

保存時の自動修正

ファイル保存時に自動的に import 順序を修正する設定:

json// .vscode/settings.json
{
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
    "source.organizeImports": false
  },
  "eslint.codeActionsOnSave.mode": "all"
}

その他のエディタ設定

WebStorm / IntelliJ IDEA

WebStorm では以下の設定で ESLint の自動修正を有効にできます:

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

Vim / Neovim

Vim での設定例(ALE プラグインを使用):

vim" .vimrc
let g:ale_fixers = {
\   'javascript': ['eslint'],
\   'typescript': ['eslint'],
\}
let g:ale_fix_on_save = 1
let g:ale_javascript_eslint_use_global = 1

具体的な整列例とビフォーアフター

基本的な整列例

Before: 順序がバラバラな状態

javascript// 修正前のコード
import { formatDate } from '../utils/date';
import React, { useState, useEffect } from 'react';
import { Button, Modal } from 'antd';
import axios from 'axios';
import { UserService } from './services/UserService';
import { API_CONFIG } from '../../config/api';
import lodash from 'lodash';
import { validateEmail } from './utils/validation';

この状態では、以下のようなエラーが発生します:

go1:1   error  `react` import should occur before import of `../utils/date`  import/order
3:1   error  `axios` import should occur before import of `antd`  import/order
4:1   error  There should be at least one empty line between import groups  import/order
7:1   error  `lodash` import should occur before import of `./services/UserService`  import/order

After: ESLint による自動整列後

javascript// 修正後のコード
import React, { useState, useEffect } from 'react';

import { Button, Modal } from 'antd';
import axios from 'axios';
import lodash from 'lodash';

import { API_CONFIG } from '../../config/api';
import { UserService } from './services/UserService';

import { formatDate } from '../utils/date';
import { validateEmail } from './utils/validation';

複雑なプロジェクト構成での例

Before: 大規模プロジェクトでの混乱状態

javascript// 修正前のコード
import { ProfileCard } from './ProfileCard';
import React, { memo, useMemo } from 'react';
import { useQuery } from '@tanstack/react-query';
import { toast } from 'react-toastify';
import { UserAvatar } from '@/components/ui/UserAvatar';
import { formatUserName } from '@/utils/user';
import { Button } from '@mui/material';
import { userApi } from '@/api/user';
import { ROUTES } from '@/constants/routes';
import { useRouter } from 'next/router';
import { Card, CardContent } from '@/components/ui/Card';

After: 適切なグループ分けと順序

javascript// 修正後のコード
import React, { memo, useMemo } from 'react';

import { Button } from '@mui/material';
import { useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import { toast } from 'react-toastify';

import { userApi } from '@/api/user';
import { Card, CardContent } from '@/components/ui/Card';
import { UserAvatar } from '@/components/ui/UserAvatar';
import { ROUTES } from '@/constants/routes';
import { formatUserName } from '@/utils/user';

import { ProfileCard } from './ProfileCard';

TypeScript での型インポート例

Before: 型と値の混在

javascript// 修正前のコード
import { UserService } from './services/UserService';
import type { User } from './types/User';
import React from 'react';
import type { FC } from 'react';
import { Button } from 'antd';
import type { ButtonProps } from 'antd';

After: 型と値の適切な分離

javascript// 修正後のコード
import type { FC } from 'react';
import React from 'react';

import type { ButtonProps } from 'antd';
import { Button } from 'antd';

import type { User } from './types/User';
import { UserService } from './services/UserService';

パフォーマンス改善の例

Before: 不必要な全体インポート

javascript// 修正前のコード
import * as lodash from 'lodash';
import * as React from 'react';
import { Button } from 'antd';
import { UserService } from './services/UserService';

After: 必要な部分のみインポート

javascript// 修正後のコード
import React from 'react';

import { Button } from 'antd';
import { debounce } from 'lodash';

import { UserService } from './services/UserService';

この変更により、バンドルサイズの削減も同時に実現できます。

実際の修正コマンドの実行例

修正プロセスの実例を見てみましょう:

bash# 修正前の状態確認
$ yarn lint src/components/UserProfile.tsx
/src/components/UserProfile.tsx
  1:1   error  `react` import should occur before import of `./ProfileCard`  import/order
  3:1   error  `@tanstack/react-query` import should occur before import of `react-toastify`  import/order
  7:1   error  There should be at least one empty line between import groups  import/order

✖ 3 problems (3 errors, 0 warnings)
  3 errors and 0 warnings potentially fixable with the `--fix` option.

# 自動修正の実行
$ yarn lint src/components/UserProfile.tsx --fix

# 修正後の確認
$ yarn lint src/components/UserProfile.tsx
✨ All files pass linting.

まとめ

ESLint の eslint-plugin-import を活用することで、import 文の順序を自動的に管理し、コードベース全体の可読性と保守性を大幅に向上させることができます。

今回ご紹介した内容をまとめると:

導入のメリット

  • コードの可読性向上
  • チーム開発での統一性確保
  • コードレビューの効率化
  • 自動修正による作業時間短縮

設定のポイント

  • プロジェクトの構造に合わせたグループ設定
  • 適切な改行とアルファベット順序の設定
  • TypeScript プロジェクトでの型インポート考慮
  • エディタ連携による開発効率の最大化

実践での注意点

  • 段階的な導入でチームへの負担を軽減
  • 既存コードベースでの一括修正時の慎重な確認
  • パフォーマンスへの影響を考慮した設定調整

import 順序の自動管理は、一度設定すれば継続的にメリットを享受できる投資です。ぜひプロジェクトに導入して、より良い開発体験を実現してください。

関連リンク