siomin_ note

0 post

    #JavaScriptNode.jsrequire-dirExpress

    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内で分岐する必要がある。


    © 2020, siomin_