ESLintプラグイン開発:あなたの「こだわり」をチームの「共通言語」に昇華させる技術
こんにちは。開発環境の設計を愛してやまないエンジニアです。
多くのエンジニアが「Prettierで自動整形して、ESLintでエラーを弾く」という開発フローを日常的にこなしていることでしょう。しかし、プロジェクトが大きくなると、「特定のライブラリはこの設定で使ってほしい」「この非推奨メソッドを意図的に排除したい」という、ドキュメントだけでは伝えきれない「暗黙のルール」が生まれます。
これを毎回PRレビューで指摘し、修正を依頼する……。そんな消耗戦を終わらせる究極の手段が、「ESLintプラグインを自作してパッケージ化すること」です。
今日は、あなたの脳内にあるコード品質の基準を、そのままコードとして社会実装する方法を伝授します。これをマスターすれば、チーム全体のコード品質が自動的に底上げされ、あなたはレビューの「細かい指摘」という重労働から解放されます。
—
1. なぜ「設定ファイル」ではなく「プラグイン」なのか?
`.eslintrc` にルールを書き連ねることも可能ですが、プロジェクトを横断してルールを共有する際、設定ファイルだけでは限界があります。
- 再利用性: 複数のリポジトリで同じルールを適用する際、プラグインなら `npm install` するだけで完了します。
- カプセル化: ルールのロジックと、そのルールを証明するテストコードをパッケージとして分離できます。
- 心理的安全性: 「個人のこだわり」ではなく「プロジェクトとして導入されたルール」という客観性が生まれ、チームの納得感が変わります。
—
2. 開発環境の構築:Yeomanで「定石」をインストールする
ESLintプラグインのプロジェクト構成を一から書くのは賢いやり方ではありません。公式が提供している `generator-eslint` を使い、ベストプラクティスが詰まった雛形を生成しましょう。
ジェネレーターをインストール
npm install -g yo generator-eslint
作業ディレクトリを作成して雛形を生成
mkdir eslint-plugin-my-rules
cd eslint-plugin-my-rules
yo eslint:plugin
質問に答えていくと、以下のような構成が生成されます
lib/rules/ <- ここにルール本体を記述
tests/lib/rules/ <- ここにルールを検証するテストを記述
この構成の美しさは、「ルール本体」と「テスト」が1対1で対応する点にあります。この構造を守ることこそが、堅牢なプラグイン開発の第一歩です。
—
3. HelloWorld:ルールを定義する
例として、「`console.log` を禁止する」というシンプルなルールを作ってみましょう。ESLintは、コードをAST(抽象構文木)というツリー構造に変換して解析します。
`lib/rules/no-console-log.js` を以下のように記述します。
module.exports = {
meta: {
type: “problem”, // ルールの性質(problem, suggestion, layout)
docs: { description: “console.logを禁止する” },
fixable: “code”, // 自動修正が可能か
},
create(context) {
return {
// MemberExpressionは、オブジェクトのプロパティアクセスを指す
MemberExpression(node) {
if (node.object.name === ‘console’ && node.property.name === ‘log’) {
context.report({
node,
message: “console.logの使用は禁止されています。代わりにloggerを使ってください。”
});
}
}
};
}
};
ここでのポイント: `create` メソッド内のオブジェクトがASTのノードタイプと対応しています。ESLintはコードのツリーを巡回しながら、この関数を呼び出します。ASTの構造を知るには [AST Explorer](https://astexplorer.net/) を使うのが現代のエンジニアの常識です。
—
4. テストを書く:品質の担保
プラグイン開発において、テストは単なる「確認作業」ではなく、「ルールの仕様書」です。
`tests/lib/rules/no-console-log.js` を開いてみてください。
const RuleTester = require(“eslint”).RuleTester;
const rule = require(“../../../lib/rules/no-console-log”);
const ruleTester = new RuleTester();
ruleTester.run(“no-console-log”, rule, {
valid: [“logger.info(‘hello’)”], // 通るコード
invalid: [
{
code: “console.log(‘hello’)”, // エラーになるべきコード
errors: [{ message: “console.logの使用は禁止されています。” }]
}
]
});
このテストを通すことで、「私のルールは誤検知をしない」という絶対的な自信を持つことができます。`npm test` を叩いて緑色に輝く瞬間、あなたはただのコーダーから「開発環境のアーキテクト」に昇格したと言えるでしょう。
—
5. ローカルでの動作確認とnpm公開の作法
作成したプラグインを自分の別プロジェクトで試すには、`npm link` が最強です。
プラグインのディレクトリで実行
npm link
適用先のプロジェクトディレクトリで実行
npm link eslint-plugin-my-rules
これで、`node_modules` 経由でローカルのプラグインが参照されます。あとは、適用先の `.eslintrc` にプラグイン名を追加して、`rules` に自作ルールを書き込むだけです。
公開に向けた最後のアドバイス
`package.json` には以下の記述を忘れずに行ってください。
- `main`: `index.js` (ルールをエクスポートするファイル)
- `peerDependencies`: `eslint` のバージョン指定(依存関係をクリーンに保つため)
- `files`: `[“lib”]` (パッケージに含まれるディレクトリを指定)
—
最後に:なぜこれをやるのか?
プログラミングは「書くこと」よりも「読み、理解し、メンテナンスし続けること」に時間の大半が費やされます。あなたの作成したプラグインは、未来の自分やチームメンバーが、コードの意図を迷わず解釈するための「道標」となります。
最初は難しく感じるかもしれませんが、一度「ルールをコードで制御する」快感を覚えたら、もう元には戻れません。さあ、あなたのこだわりをパッケージにして、開発現場に革命を起こしましょう!
何か詰まったら、いつでもAST Explorerと向き合ってみてください。コードの裏側の構造が見えたとき、あなたは本当の意味でJavaScriptを支配できるようになりますよ。応援しています!