結論
- ESLint の no-restricted-imports ルールを使用する
背景
axios などの HTTP クライアント、New Relic や Datadog などの分析・トラッキングライブラリ、winston などのロギングライブラリを使用するとき、設定値を共通化したり、常に特定のパラメータを付与するために、ラッパーを用意することがあります。
しかし、ラッパーを用意しただけでは開発者が誤って、あるいは知らずに生のライブラリを直接 import して使ってしまう可能性があります。
// ラッパーを作成。これを開発者に使ってほしい
import axios from "axios";
export const httpClient = axios.create({
headers: {
"X-API-Key": process.env.API_KEY, // すべてのリクエストにAPIキーを付与
},
});
// 別ファイルでの使用例
// ✅ ラッパーを使用
import { httpClient } from "src/lib/httpClient";
const response = await httpClient.get("/api/users");
// ヘッダー: { "X-API-Key": "..." }
// ❌ 生のaxiosを直接importして使用
import axios from "axios";
const response = await axios.get("/api/users");
// ヘッダー: {} ← 必要なヘッダーが欠落!
レビューで防ぐのは大変なので、自動化したいところです。
解決策: ESLintで特定パッケージの import を禁止する
ESLint の no-restricted-imports ルールを使うと、指定したパッケージの import を禁止できます。
設定方法
module.exports = {
rules: {
"no-restricted-imports": [
"error",
{
paths: [
{
name: "axios",
message: "代わりに 'src/lib/httpClient' を使用してください。",
},
],
},
],
},
};
この設定により、禁止されているパッケージを import すると ESLint エラーが発生します。
ラッパーの実装
このままではラッパー実装ファイル自体でもエラーが出てしまうので、ファイルの先頭に eslint-disable コメントを追加して、ルールを無効化します。
/* eslint-disable no-restricted-imports */
import axios from "axios";
export const httpClient = axios.create({
headers: {
"X-API-Key": process.env.API_KEY,
},
});
複数パッケージへの適用
複数のライブラリを禁止したい場合は、paths 配列に追加してください。
module.exports = {
rules: {
"no-restricted-imports": [
"error",
{
paths: [
{
name: "axios",
message: "代わりに 'src/lib/httpClient' を使用してください。",
},
{
name: "winston",
message: "代わりに 'src/lib/logger' を使用してください。",
},
{
name: "@datadog/browser-rum",
message: "代わりに 'src/lib/analytics' を使用してください。",
},
],
},
],
},
};
また、特定のパターンにマッチするパッケージをすべて禁止したい場合は、patterns が使用できます。
module.exports = {
rules: {
"no-restricted-imports": [
"error",
{
patterns: [
{
group: ["@aws-sdk/*"],
message: "代わりに 'src/lib/awssdk' を使用してください。",
},
],
},
],
},
};
まとめ
ESLint の no-restricted-imports ルールを使うことで、特定のパッケージの import を禁止し、ラッパーの使用を強制できます。
設定は簡単なので、ぜひ活用してみてください。
参考リンク
注意事項
本ブログに掲載している内容は、私個人の見解であり、所属する組織の立場や戦略、意見を代表するものではありません。
あくまでエンジニアとしての経験や考えを発信していますので、ご了承ください。
