require-dirでモジュールを一括require【Node.js】
April 08, 2020
require-dir
は指定されたディレクトリのjsモジュールをまとめてrequireしてくれる便利なモジュールです。
インストール
npm install require-dir
# yarn を使う場合
yarn add require-dir
ディレクトリ構成例
root
├ index.js
└ modules
├ a.js
├ b.js
├ c.js
└ other/
index.jsから require-dir
を使ってmodules内のモジュールをrequireします。
サンプルとして other
というディレクトリを入れてありますが、 require-dir
は .js
ファイル以外を無視してくれます。
a.js
module.exports = function () {
...
}
各jsファイルの中身は関数をexportする単純なものです。
基本的な使い方
index.js
const requireDir = require('require-dir')
// 読み込みたいモジュールがあるディレクトリのパスを入れる
const modules = requireDir('./modules')
// { a: [Function], b: [Function], c: [Function] }
.js
を除いたファイル名がキーとなって、requireされたオブジェクトが取得できます。
どんな時に使うの?
モジュールを一括でrequireしたい時はもちろんですが、
ファイル名がキーとなるので、ExpressのRouterなどに使うとメンテナンスのしやすさやコードの見通しが良くなります。
Expressでの使用例
ディレクトリ構成
root
├ app.js
└ routes
│ a.js
└ b.js
a.js
const router = require('express').Router()
router.get('/' (req, res) => {
res.send('ok')
})
module.exports = router
app.useに渡す
app.js
const express = require('express')
const app = express()
const requireDir = require('require-dir')
// routesにあるRouterを全てrequireする
const routes = requireDir('./routes')
// キーを元にしたした配列を作る
Object.keys(routes).forEach(fileName => {
// ファイル名をルート名とする
// forEachを使い app.use に router を渡す
app.use(`/${ fileName }`, routes[fileName])
})
const listener = app.listen(process.env.PORT || 3000, () => {
console.log("listening on port " + listener.address().port);
});
ひとつずつrequireする必要がないので楽です。
さらに!
ルートごとにディレクトリで管理したいと思うことがあるはずです。
例えばこういうディレクトリ構成 ↓
root
├ app.js
└ routes
├ a
│ └ index.js
└ b
└ index.js
そんな時は require-dir
にオプションを与えます。
const routes = requireDir('./routes', {
recurse: true
})
// {
// a: { index: [Function: router] },
// b: { index: [Function: router] }
// }
このように、指定したディレクトリの中まで参照してくれるようになります。
上記の方法に合わせて書き換える
app.js
const express = require('express')
const app = express()
const requireDir = require('require-dir')
const routes = requireDir('./routes', {
recurse: true
})
Object.keys(routes).forEach(fileName => {
// routes[filename] の中の index を指定する
app.use(`/${ fileName }`, routes[fileName].index)
})
const listener = app.listen(process.env.PORT || 3000, () => {
console.log("listening on port " + listener.address().port);
});
これでルートが無限に増えても安心です。
残念な点・ …url/:id のようなルートパラメーターが設定できない。
・ ミドルウェアを挟みたい場合はforEach内で分岐する必要がある。