ESLint シェアラブル設定の設計術:単一ソースで Web/Node/React をカバー

複数のプロジェクトで同じ ESLint ルールを使いたいと思ったことはありませんか。Web アプリケーション、Node.js サーバー、React コンポーネントなど、異なる環境のプロジェクトを管理していると、それぞれに ESLint 設定を書くのは非効率です。
シェアラブル設定を活用すれば、一度設定を作るだけで複数のプロジェクトに適用でき、保守性も大幅に向上します。本記事では、単一の ESLint シェアラブル設定パッケージで Web・Node.js・React の環境をカバーする設計術をご紹介しましょう。
背景
ESLint シェアラブル設定とは
ESLint シェアラブル設定は、ESLint のルール設定を npm パッケージとして配布し、複数のプロジェクトで再利用できる仕組みです。eslint-config-
というプレフィックスをつけて公開することで、他のプロジェクトから簡単に読み込めるようになります。
有名なものには eslint-config-airbnb
や eslint-config-standard
などがありますね。これらは何千ものプロジェクトで使われており、その有用性が証明されています。
単一パッケージで複数環境をサポートする意義
従来は環境ごとに別々の設定パッケージを作ることもありましたが、以下の課題がありました。
- パッケージが増えるほど管理コストが上がる
- 共通ルールの変更時に複数パッケージを修正する必要がある
- バージョン管理が煩雑になる
単一パッケージ内で複数の環境設定を提供することで、これらの課題を解決できます。
以下の図は、シェアラブル設定パッケージと各プロジェクトの関係を示しています。
mermaidflowchart TB
pkg["eslint-config-myteam<br/>(シェアラブル設定パッケージ)"]
subgraph configs["設定ファイル群"]
base["base.js<br/>(共通設定)"]
web["web.js<br/>(Web 用)"]
node["node.js<br/>(Node.js 用)"]
react["react.js<br/>(React 用)"]
end
subgraph projects["各プロジェクト"]
pj1["Web アプリ"]
pj2["Node.js API"]
pj3["React SPA"]
end
pkg --> configs
base --> web
base --> node
base --> react
web --> pj1
node --> pj2
react --> pj3
このアーキテクチャにより、共通ルールは base.js
に集約され、環境固有の設定だけを各ファイルに記述できます。
課題
環境ごとに異なるルールセット
Web ブラウザ、Node.js、React では、それぞれ利用できる API や推奨されるコーディングスタイルが異なります。
# | 環境 | 特徴 | 必要なルール例 |
---|---|---|---|
1 | Web ブラウザ | DOM API、グローバル変数(window, document) | no-restricted-globals |
2 | Node.js | CommonJS、Node API(fs, path) | node/no-unsupported-features |
3 | React | JSX 構文、Hooks ルール | react/jsx-uses-react , react-hooks/rules-of-hooks |
これらの違いを考慮しつつ、共通部分はなるべく重複させずに設計する必要があります。
依存関係の肥大化
すべての環境に対応しようとすると、多くの ESLint プラグインをインストールすることになります。しかし、Node.js プロジェクトで React プラグインは不要ですよね。
無駄な依存関係を避けつつ、必要なプラグインだけをインストールできる仕組みが求められます。
以下の図は、依存関係の最適化イメージを示したものです。
mermaidflowchart LR
subgraph opt["最適化後"]
direction TB
node_pj["Node.js<br/>プロジェクト"] -->|必要なもののみ| node_deps["eslint<br/>eslint-plugin-node"]
end
subgraph before["最適化前"]
direction TB
node_pj2["Node.js<br/>プロジェクト"] -->|すべて| all_deps["eslint<br/>eslint-plugin-node<br/>eslint-plugin-react<br/>..."]
end
before -.->|改善| opt
解決策
パッケージ構造の設計
単一パッケージ内で複数の設定ファイルを提供し、プロジェクトが必要な設定だけを選択できるようにします。以下のようなディレクトリ構造が効果的です。
csharpeslint-config-myteam/
├── package.json
├── index.js # デフォルト(base と同じ)
├── base.js # 共通設定
├── web.js # Web ブラウザ用
├── node.js # Node.js 用
└── react.js # React 用
各設定ファイルは独立して読み込めるため、プロジェクトは .eslintrc.js
で必要なものだけを指定できます。
共通設定の抽出
すべての環境で共通するルールを base.js
に集約します。これにより、ルール変更時の修正が一箇所で済みますね。
共通ルールには以下のようなものが含まれます。
- 構文エラーを検出するルール(
no-undef
,no-unused-vars
など) - コードスタイルルール(
indent
,quotes
,semi
など) - ベストプラクティス(
eqeqeq
,no-eval
など)
javascript// base.js - 共通設定
module.exports = {
env: {
es2021: true,
},
parserOptions: {
ecmaVersion: 12,
sourceType: 'module',
},
rules: {
// 構文エラー検出
'no-undef': 'error',
'no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
},
],
// コードスタイル
indent: ['error', 2],
quotes: ['error', 'single'],
semi: ['error', 'always'],
// ベストプラクティス
eqeqeq: ['error', 'always'],
'no-eval': 'error',
'no-implied-eval': 'error',
},
};
この設定は、どの環境でも有効な普遍的なルールのみを含んでいます。
環境別設定の継承
各環境の設定ファイルは base.js
を継承し、環境固有のルールだけを追加します。ESLint の extends
機能を使えば、継承関係を簡潔に表現できますね。
以下は Web ブラウザ用の設定例です。
javascript// web.js - Web ブラウザ用設定
module.exports = {
// 共通設定を継承
extends: ['./base.js'],
env: {
browser: true,
},
rules: {
// ブラウザ特有のルール
'no-restricted-globals': [
'error',
'event', // 非推奨のグローバル変数
'fdescribe', // テストフレームワークの誤用防止
],
},
};
browser: true
を指定することで、window
や document
などのグローバル変数がエラーにならなくなります。
次に Node.js 用の設定を見てみましょう。
javascript// node.js - Node.js 用設定
module.exports = {
extends: ['./base.js'],
env: {
node: true,
},
plugins: ['node'],
rules: {
// Node.js 特有のルール
'node/no-unsupported-features/es-syntax': [
'error',
{ version: '>=14.0.0' },
],
'node/no-missing-require': 'error',
'node/no-extraneous-require': 'error',
},
};
Node.js 環境では、CommonJS の require
や Node API に関するルールを追加します。
最後に React 用の設定です。
javascript// react.js - React 用設定
module.exports = {
extends: [
'./base.js',
'./web.js', // React は Web 環境なので web.js も継承
],
parserOptions: {
ecmaFeatures: {
jsx: true, // JSX 構文を有効化
},
},
plugins: ['react', 'react-hooks'],
settings: {
react: {
version: 'detect', // インストール済みの React バージョンを自動検出
},
},
rules: {
// React 特有のルール
'react/jsx-uses-react': 'error',
'react/jsx-uses-vars': 'error',
'react/prop-types': 'warn',
// Hooks ルール
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
},
};
React 設定は web.js
も継承することで、ブラウザ環境のルールも適用されます。
以下の図は、設定ファイル間の継承関係を示しています。
mermaidflowchart TB
base["base.js<br/>(共通ルール)"]
web["web.js<br/>(ブラウザ環境)"]
node["node.js<br/>(Node.js 環境)"]
react["react.js<br/>(React)"]
base -->|継承| web
base -->|継承| node
base -->|継承| react
web -->|継承| react
style base fill:#e1f5ff
style web fill:#fff4e1
style node fill:#e8f5e1
style react fill:#ffe1f5
図で理解できる要点:
- すべての設定は
base.js
を起点とする react.js
はweb.js
とbase.js
の両方を継承- 継承により重複コードを排除できる
peerDependencies の活用
各環境で必要なプラグインは peerDependencies
として定義します。これにより、プロジェクト側で必要なプラグインだけをインストールできますね。
json{
"name": "eslint-config-myteam",
"version": "1.0.0",
"description": "Shareable ESLint config for Web/Node/React",
"main": "index.js",
"peerDependencies": {
"eslint": ">=8.0.0"
},
"peerDependenciesMeta": {
"eslint-plugin-node": {
"optional": true
},
"eslint-plugin-react": {
"optional": true
},
"eslint-plugin-react-hooks": {
"optional": true
}
}
}
peerDependenciesMeta
で optional: true
を指定することで、プロジェクトが必要に応じてインストールできるようになります。
エントリーポイントの設定
index.js
をデフォルトのエントリーポイントとし、最も汎用的な設定を提供します。
javascript// index.js - デフォルト設定
module.exports = {
extends: ['./base.js'],
};
シンプルに base.js
を継承するだけで、環境を指定しないプロジェクトでも利用できます。
具体例
パッケージの公開
作成したシェアラブル設定を npm に公開します。パッケージ名は eslint-config-
で始める必要があります。
bash# パッケージディレクトリで実行
yarn init
# package.json を編集後
yarn publish
公開後は、他のプロジェクトから yarn add
でインストールできるようになりますね。
Web プロジェクトでの利用
Web ブラウザ向けプロジェクトでは、シェアラブル設定の web
部分を指定します。
bash# 必要なパッケージをインストール
yarn add -D eslint eslint-config-myteam
プロジェクトの .eslintrc.js
で設定を読み込みます。
javascript// .eslintrc.js - Web プロジェクト
module.exports = {
extends: ['myteam/web'],
// プロジェクト固有の設定があれば追加
rules: {
// 例: このプロジェクトでは console.log を許可
'no-console': 'off',
},
};
eslint-config-
プレフィックスは省略でき、myteam/web
と書くだけで eslint-config-myteam
パッケージの web.js
が読み込まれます。
Node.js プロジェクトでの利用
Node.js サーバーアプリケーションでは、node
設定を使用します。
bash# Node.js 用プラグインも追加
yarn add -D eslint eslint-config-myteam eslint-plugin-node
プロジェクトの .eslintrc.js
で Node.js 用設定を指定します。
javascript// .eslintrc.js - Node.js プロジェクト
module.exports = {
extends: ['myteam/node'],
// プロジェクト固有の設定
rules: {
// 例: 開発中は console.log を許可
'no-console':
process.env.NODE_ENV === 'production'
? 'error'
: 'off',
},
};
Node.js 環境特有のルールが適用され、CommonJS や Node API の使用が適切にチェックされます。
React プロジェクトでの利用
React アプリケーションでは、React と React Hooks のプラグインも必要です。
bash# React 用プラグインを含めてインストール
yarn add -D eslint eslint-config-myteam eslint-plugin-react eslint-plugin-react-hooks
.eslintrc.js
で React 設定を指定します。
javascript// .eslintrc.js - React プロジェクト
module.exports = {
extends: ['myteam/react'],
// プロジェクト固有の設定
rules: {
// 例: prop-types は TypeScript を使うので無効化
'react/prop-types': 'off',
},
};
JSX 構文や Hooks のルールが適用され、React のベストプラクティスに沿った開発ができますね。
以下の図は、各プロジェクトでの設定読み込みフローを示しています。
mermaidsequenceDiagram
participant PJ as プロジェクト
participant RC as .eslintrc.js
participant PKG as eslint-config-myteam
participant BASE as base.js
participant ENV as 環境設定(web/node/react)
PJ->>RC: ESLint 実行
RC->>PKG: extends: ['myteam/web']
PKG->>ENV: web.js を読み込み
ENV->>BASE: base.js を継承
BASE-->>ENV: 共通ルールを提供
ENV-->>PKG: 環境固有ルールを追加
PKG-->>RC: 統合された設定を返す
RC-->>PJ: リントを実行
図で理解できる要点:
- プロジェクトは環境別設定を指定するだけでよい
- 継承関係により共通ルールが自動的に適用される
- 各段階で設定が統合され、最終的な設定が生成される
複数環境の組み合わせ
一つのプロジェクトで複数の環境を使い分けることもできます。例えば、Node.js サーバーに React の管理画面が含まれる場合などです。
javascript// .eslintrc.js - ハイブリッドプロジェクト
module.exports = {
// デフォルトは Node.js 設定
extends: ['myteam/node'],
overrides: [
{
// src/client ディレクトリは React 設定
files: ['src/client/**/*.{js,jsx}'],
extends: ['myteam/react'],
},
],
};
overrides
を使えば、ファイルパスに応じて異なる設定を適用できますね。
TypeScript 対応の追加
TypeScript プロジェクトにも対応させるには、TypeScript 用の設定ファイルを追加します。
javascript// typescript.js - TypeScript 用設定
module.exports = {
extends: ['./base.js'],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
rules: {
// JavaScript のルールを無効化し、TypeScript 版を使用
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
},
],
// TypeScript 特有のルール
'@typescript-eslint/explicit-function-return-type':
'warn',
'@typescript-eslint/no-explicit-any': 'warn',
},
};
TypeScript では JavaScript のルールの一部を無効化し、TypeScript 対応版のルールに置き換える必要があります。
React + TypeScript の組み合わせも簡単に対応できます。
javascript// react-typescript.js - React + TypeScript 用設定
module.exports = {
extends: ['./typescript.js', './react.js'],
rules: {
// TypeScript を使う場合は prop-types は不要
'react/prop-types': 'off',
},
};
このように、既存の設定を組み合わせることで、新しい環境への対応も効率的に行えますね。
設定のテスト
シェアラブル設定が正しく動作するか、テストを書くことをお勧めします。
javascript// test/configs.test.js
const { ESLint } = require('eslint');
const path = require('path');
describe('ESLint Configs', () => {
test('base config loads successfully', async () => {
const eslint = new ESLint({
useEslintrc: false,
baseConfig: require('../base.js'),
});
const results = await eslint.lintText('const x = 1;');
expect(results[0].errorCount).toBe(0);
});
test('web config detects browser globals', async () => {
const eslint = new ESLint({
useEslintrc: false,
baseConfig: require('../web.js'),
});
// window はエラーにならない
const results = await eslint.lintText(
'window.addEventListener("load", () => {});'
);
expect(results[0].errorCount).toBe(0);
});
});
テストを書くことで、設定変更時の影響を確認でき、品質を保てます。
バージョン管理とリリース
シェアラブル設定のバージョンは Semantic Versioning に従うべきです。
# | バージョン変更 | 内容 |
---|---|---|
1 | Major(例: 1.0.0 → 2.0.0) | 既存ルールの厳格化、破壊的変更 |
2 | Minor(例: 1.0.0 → 1.1.0) | 新しいルールの追加、非破壊的変更 |
3 | Patch(例: 1.0.0 → 1.0.1) | バグ修正、ドキュメント更新 |
ルールを厳しくする変更は、既存プロジェクトで新たなエラーを引き起こす可能性があるため、Major バージョンアップとして扱います。
bash# Minor バージョンアップの例
yarn version minor
yarn publish
CHANGELOG.md を用意し、変更内容を記録することも重要ですね。
まとめ
ESLint のシェアラブル設定を単一パッケージで設計することで、複数の環境に対応しつつ保守性の高いコード品質管理が実現できます。
本記事でご紹介した設計パターンのポイントは以下の通りです。
- 共通ルールを
base.js
に集約し、環境別設定で継承する - 複数の設定ファイルを提供し、プロジェクトが必要なものを選択できるようにする
peerDependencies
とpeerDependenciesMeta
で依存関係を最適化するoverrides
を活用して、一つのプロジェクト内で複数環境に対応する
このアプローチにより、組織全体でコードスタイルを統一しながら、各プロジェクトの特性に応じた柔軟な設定が可能になります。新しい環境への対応も既存設定の組み合わせで実現でき、拡張性も高いですね。
ぜひあなたのチームでもシェアラブル設定を導入し、効率的なコード品質管理を実現してください。
関連リンク
- article
ESLint シェアラブル設定の設計術:単一ソースで Web/Node/React をカバー
- article
ESLint Flat Config 速見表:files/ignores/plugins/rules/languageOptions の書き方
- article
ESLint を Yarn + TypeScript + React でゼロから構築:Flat Config 完全手順(macOS)
- article
ESLint vs Biome vs Rome 後継:速度・エコシステム・移行コストを実測比較
- article
ESLint の extends が効かない問題を斬る:Flat Config の files/ignores 落とし穴
- article
ESLint Flat Config 完全理解:eslint.config.js 時代の設計指針
- article
ESLint シェアラブル設定の設計術:単一ソースで Web/Node/React をカバー
- article
Dify 中心のドメイン駆動設計:ユースケースとフローの境界づけ
- article
Python クリーンアーキテクチャ実践:依存逆転と境界インタフェースの具体化
- article
Cursor 前提の開発プロセス設計:要求 → 設計 → 実装 → 検証の短サイクル化
- article
Cline 中心の開発プロセス設計:要求 → 設計 → 実装 → 検証の最短動線
- article
Prisma Driver Adapters 導入手順:libSQL/Turso・Neon の最短セットアップ
- blog
iPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
- blog
Googleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
- blog
【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
- blog
Googleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
- blog
Pixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
- blog
フロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来