-
Notifications
You must be signed in to change notification settings - Fork 2
Create a 12 factor compliant configuration system
This wiki page aims to provide you with a practical way to implement a config system that satisfies the principles outlined by 12 factor webiste.
As exemple we will setup an app that needs to configure a mongoose instance on startup.
`-- your-app-name/
|-- src/
| |-- configs/
| | |-- envs.js
| | |-- mongoose.js
| | `-- index.js
| `-- app.js
|-- .env
`-- package.json
This is a file used to overwrite default hard-coded configs.
This demo content
replaces the default mongoose URI of our app with an offline one.
your-app-name_mongoose_uri=mongodb://user:password@offline_dev_host:port/database
This file is used internally to load the environment
variables contained in the previously mentioned .env
file using node-env-file
.
It also converts all environment variables into an object with
env-dot-prop
using a namespace ('your-app-name'
) to
filter unnecessary node defaults env vars.
See this to understand how
env-dot-prop parses the env vars.
const path = require('path');
const envDotProp = require('env-dot-prop');
const env = require('node-env-file');
const appRoot = require('app-root-path');
const envPath = path.join(appRoot, '.env'); // The path of the '.env' file
const namespace = 'your-app-name';
// Gets the .env file
try {
// The file may not exist, so we need a try catch block
env(envPath, {overwrite: true});
} catch (err) {}
// Parses the environment vars.
const configs = envDotProp.get(namespace, {parse: true, caseSensitive: true});
// => { mongoose: { uri: 'mongodb://user:password@offline_dev_host:port/database' } }
module.exports = configs;
Then we need to create an ad-hoc config file to provided hard-coded defaults.
In your app, you can create one for each package you need to provide configs to.
This structure will help you to keep configs clean and well organized.
const _ = require('lodash');
const envs = require('./envs'); // The file previously created
const defaults = {
uri: 'mongodb://user:password@online_dev_host:port/database',
options: {
// Opt-in for the new connection logic of mongoose 4.11.x
useMongoClient: true,
// Good way to make sure mongoose never stops trying to reconnect
reconnectTries: Number.MAX_VALUE
}
};
// We overwrite defaults using environment variables.
// And then we export them.
module.exports = _.extend(defaults, envs.mongoose);
This file is used to export all configuration files available in the configs
folder.
In this case, there is only the mongose.js
file, but ideally here you will
add all other config files you will create for your app.
module.exports = {
mongoose: require('./mongoose')
};
Now you can import configs
whenever you need configurations in your app.
const mongoose = require('mongoose');
const configs = require('./configs/'); // Our cool config object
mongoose.connect(configs.mongoose.uri, configs.mongoose.options);