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 の自動修正を有効にできます:
Preferences
→Languages & Frameworks
→JavaScript
→Code Quality Tools
→ESLint
Automatic ESLint configuration
を選択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 順序の自動管理は、一度設定すれば継続的にメリットを享受できる投資です。ぜひプロジェクトに導入して、より良い開発体験を実現してください。
関連リンク
- blog
「QA は最後の砦」という幻想を捨てる。開発プロセスに QA を組み込み、手戻りをなくす方法
- blog
ドキュメントは「悪」じゃない。アジャイル開発で「ちょうどいい」ドキュメントを見つけるための思考法
- blog
「アジャイルコーチ」って何する人?チームを最強にする影の立役者の役割と、あなたがコーチになるための道筋
- blog
ペアプロって本当に効果ある?メリットだけじゃない、現場で感じたリアルな課題と乗り越え方
- blog
TDDって結局何がいいの?コードに自信が持てる、テスト駆動開発のはじめの一歩
- blog
「昨日やったこと、今日やること」の報告会じゃない!デイリースクラムをチームのエンジンにするための3つの問いかけ