node.js で設定ファイルを作成したい時に便利なライブラリ「node-convict」の紹介です。
プロジェクトを行う上で、' 特定フォルダのパス ' から ' 環境変数 ' 、' DBのコネクション '、その他に 共通の定数をまとめた 設定ファイルを 作成することは多々あります。
そのような config ファイルを作成する方法は いくらでもありますが、簡単に 設定ファイルを作成できる ライブラリが 「node-convict
」です。
また、' node-convict ' は Firefoxで有名な Mozillaが開発しています。
- 型チェックまで含めた 汎用的に使える設定ファイルを作成できる
' node-convict ' は node.js 用 のパッケージなので、コマンドライン上から npm
又は yarn
コマンド を使って入手します。
# npm
npm install convict --save-dev
# yarn
yarn add convict --dev
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
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})
// ]
};
以上が ' node-convict ' の紹介でした。 しっかりとしたconfigファイルを作成したい時、プロジェクト全体に適応する定数、その他 環境変数の定義や バリデーション用の型を1つに管理 する時に役立つライブラリなので 活躍する場面も多いと思います。
GitHub : mozilla/node-convict