node.jsで設定ファイル作成に便利なライブラリ「node-convict」



node.js で設定ファイルを作成したい時に便利なライブラリ「node-convict」の紹介です。

 プロジェクトを行う上で、' 特定フォルダのパス ' から ' 環境変数 ' 、' DBのコネクション '、その他に 共通の定数をまとめた 設定ファイルを 作成することは多々あります。

 そのような config ファイルを作成する方法は いくらでもありますが、簡単に 設定ファイルを作成できる ライブラリが 「node-convict」です。

また、' node-convict ' は Firefoxで有名な Mozillaが開発しています。
 

node-convict で出来ること

- 型チェックまで含めた 汎用的に使える設定ファイルを作成できる
 

node-convict のインストール

 ' node-convict ' は node.js 用 のパッケージなので、コマンドライン上から npm 又は yarn コマンド を使って入手します。

# npm
npm install convict --save-dev
# yarn
yarn add convict --dev


node-convict の使い方

 node-convict は ' convict() 'メソッド に オブジェクトのスキーマを記述して使用します。

下のスニペットの例だと、' env ' が configのキー名、 ' default ' 内の値が設定値になり、' convict.get(キー名) ' メソッドで値を取り出す事ができます。

const convict = require("convict");
// 設定の定義
let conf = convict({
  // envオブジェクトの体後
  env: { 
    default: "develop" // envの値
  } // ! env
});
// envの呼び出し
conf.get('env') // develop


ネストさせた深い階層のオブジェクトも簡単に定義できます。

const convict = require("convict");

let conf = convict({
  base: {
    nested: {
      default: "nested !!"
    }
  } // ! base
});
// ネストしたの呼び出し
conf.get('base').nested // nested config


 また、オブジェクト内に ' doc ' を定義するとオブジェクトの説明、' format 'を指定すると default内の値の型を指定することが出来ます。

* 用意されているformatタイプ
- String, Object, Array, Number, RegExp
- int, port, ipaddress, url, email
- duration ( ミリ秒、日にちなど * 3000, " 2 days" など  )
- timestamp

const convict = require("convict");

let config = convict({
  database : {
    host: {
      doc: "データベースのIPアドレス",
      format: "ipaddress", // ipアドレスにフォーマットを指定
      // default: "127.0.0.111111", // error
      default: "127.0.0.1",
    },
    user: {
      doc: "DBのユーザー名",
      format: String, // 文字列に指定
      default: "dbuser"
    },
    // .....
  }
});

// このオプションがあると値の型が強制される
config.validate({ allowed: "strict" });

config.get('database').host; // 127.0.0.1
config.get('database').user; // dbuser

 
' format 'メソッドにコールバックを渡せば、独自の validation を定義することも可能です。

var config = convict({
  key: {
    doc: "API key",
    format: function check (val) {
      if (!/^[a-fA-F0-9]{64}$/.test(val)) {
        throw new Error('must be a 64 character hex key')
      }
    },
    default: '3cec609c9bc601c047af917a544645c50caf8cd606806b4e0a23312441014deb'
  }
});


 パスワードや、暗号化用のsaltなど、直接記述したくない情報がある時は、外部JSONファイルに値を記述し、読み出すことが可能です。

// config.json
{
  "password": "secret password"
}
// jsファイル
const convict = require("convict");
const path = require('path');

let conf = convict({
  password: {
    doc : "some secret value",
    format : "*",
    default: "" // 値は 外部jsonファイルから呼び出す
  }
})
.loadFile(path.join(__dirname, 'config.json')) // config.jsonファイルから読み込み
.validate();

console.log(conf.get('password')); // secret password


 一度定義したキーの値を書き換えることも可能で、' reset(キー名) ' メソッド でキーの値を消去、 ' set(キー名)' メソッドを使えば新しい値がセットされます

const convict = require("convict");
const path = require('path');

let config = convict({
  secret: {
    doc : "some secret value",
    format : "*",
    default: "" // 値は 外部jsonファイルから呼び出す
  }
})
.loadFile(path.join(__dirname, 'config.json')).validate();

console.log(config.get('secret')); // secret-password

config.reset('secret'); // secretの値をリセット
config.set('secret', 'new-password'); // secretの新しい値を定義

console.log(config.get('secret')); // new-password


webpackの ファイル用 ' module.rules '  を別ファイルで管理してみる

 node.js をベースに進めているプロジェクトは限られてくるかもしれませんが、' babel ', ' webpack', タスクランナーの ' gulp '  など、 既に node.jsを部分的に使っているところは多いと思われます。

 実用的な例として、" node-convict " を使って webpackのconfigファイルの ' rules ' を別ファイルに分離して、見通しが良くなるように 少しスッキリさせてみました。

下記のスニペットは 自身のプロジェクトで使っている webpack用のconfigファイルです。
( * わかり易くする為、node-convict を適応させる部分以外は コメントアウトしています )

// ! node-convict 適応前のコード
// template.webpack.config.js
const webpack = require("webpack");
const path = require("path");
const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  // entry: {
  //   front: "./tpl/js/front.js",
  //   tpl: [
  //     "./tpl/bundle-css.js",
  //     "./tpl/bundle.js"
  //   ]
  // },
  // output: {
  //   path: path.resolve(__dirname, "static/bundles"),
  //   filename: "[name].js"
  // },
  module: {
    // この部分を分離する
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader"
      }, // ! .js
      {
        // CSSファイル用の処理
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          use: ["css-loader"]
        })
      }, // ! .css
      {
        // SASSファイル用の処理
        test: /\.s[ac]ss$/,
        use: ExtractTextPlugin.extract({
          use: ["css-loader", "sass-loader"]
        })
      }, // ! sass, scss
      {
        // スタイルシート以外のファイルの処理
        test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/,
        loader: "file-loader",
        options: {
          name: "[name].[ext]"
        }
      } // ! png,jpeg, fonts.. and so

    ] // ! rules
  }, // ! module
  // externals: {
  //   jquery: "jQuery"
  // },
  // plugins: [
  //   new ExtractTextPlugin("[name].css"),
  //   new webpack.optimize.UglifyJsPlugin({
  //     comments: false,
  //     compress: {
  //       warnings: false
  //     }
  //   }),
  //   // CSSファイルを圧縮
  //   new webpack.LoaderOptionsPlugin({minimize: true})
  // ]
};


 下のスニペットが webpackの ' rules ' 用の configファイルです。" オブジェクト名 : ' default ' " 内に 各種ファイル用の ルールの振る舞いをそのまま記述しています。

 誰が見てもわかりやすいように ' doc ' には 値がどのような役割をしているかの説明、また、webpack用の ルールは基本 'オブジェクト' 型なので、 値の型を ' Object ' に指定しています。

// config/webpackConfig.js
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const convict = require("convict");

// webpackの rules用config
let webpackConfig = convict({
  rule: {
    js: {
      doc: "javascript用の振る舞い",
      format: Object,
      default: {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader"
      } // ! default
    }, // js
    css: {
      doc: "css用の振る舞い",
      format: Object,
      default: {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          use: ["css-loader"]
        })
      } // ! default
    }, // ! css
    sass: {
      doc: "sass, scss用の振る舞い",
      format: Object,
      default: {
        test: /\.s[ac]ss$/,
        use: ExtractTextPlugin.extract({
          use: ["css-loader", "sass-loader"]
        })
      } // ! default
    }, // ! sass
    file: {
      doc: "画像やフォントファイル用の振る舞い",
      format: Object,
      default: {
        test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/,
        loader: "file-loader",
        options: {
          name: "[name].[ext]"
        }
      } // ! default
    } // ! file
  } // ! rule
});

webpackRules.validate({ allowed: "strict" });

module.exports = webpackConfig;


 下記が ' node-convict ' を使って ルールを適応したファイルです。各種ファイル用の振る舞いが 1行で済むようになりました。
( * わかり易くする為、node-convict を適応させる部分以外は コメントアウトしています )

// ! node-convictを適応させたファイル
// template.webpack.config.js
const webpack = require("webpack");
const path = require("path");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
// ルール用のコンフィグファイルの読み込み
const wpConf = require('./config/webpackConfig')

module.exports = {
  // entry: {
  //   front: "./tpl/js/front.js",
  //   tpl: [
  //     "./tpl/bundle-css.js",
  //     "./tpl/bundle.js"
  //   ]
  // }, // entry
  // output: {
  //   path: path.resolve(__dirname, "static/bundles"),
  //   filename: "[name].js"
  // },
  module: {
    // convictを使って webpack rulesを別ファイルで管理
    rules: [
      wpConf.get('rule').js, // js用のルールを呼び出し
      wpConf.get('rule').css, // css用のルールを呼び出し
      wpConf.get('rule').sass,
      wpConf.get('rule').file

    ] // ! rules
  }, // ! module
  // externals: {
  //   jquery: "jQuery"
  // },
  // plugins: [
  //   new ExtractTextPlugin("[name].css"),
  //
  //   new webpack.optimize.UglifyJsPlugin({
  //     comments: false,
  //     compress: {
  //       warnings: false
  //     }
  //   }),
  //   new webpack.LoaderOptionsPlugin({minimize: true})
  // ]
};


Summary

 以上が ' node-convict ' の紹介でした。 しっかりとしたconfigファイルを作成したい時、プロジェクト全体に適応する定数、その他 環境変数の定義や バリデーション用の型を1つに管理 する時に役立つライブラリなので 活躍する場面も多いと思います。

GitHub :  mozilla/node-convict

 

この記事のカテゴリ
プログラミング

この記事に付けられているタグ



その他の運営サービス

最新の記事