我一直在开发一些Node应用程序,我一直在寻找一种存储部署相关设置的良好模式。在Django世界(我来自那里),常见的做法是有一个settings.py文件包含标准设置(时区等),然后有一个local_settings.py用于部署特定的设置,即。要与什么数据库通信、什么memcache套接字、管理员的电子邮件地址等等。

我一直在为Node寻找类似的模式。只要一个配置文件就好了,这样它就不必与app.js中的其他所有东西挤在一起,但我发现有一种方法在源代码控制之外的文件中拥有特定于服务器的配置很重要。同一款应用可以部署在不同设置的服务器上,必须处理合并冲突,这不是我的乐趣所在。

那么是否存在某种框架/工具,或者每个人都只是自己拼凑一些东西?


当前回答

npm i config

In config/default.json
{
    "app": {
        "port": 3000
    },
    "db": {
        "port": 27017,
        "name": "dev_db_name"
    }
}

In config/production.json
{
    "app": {
        "port": 4000
    },
    "db": {
        "port": 27000,
        "name": "prod_db_name"
    }
}

In index.js

const config = require('config');

let appPort = config.get('app.port');
console.log(`Application port: ${appPort}`);

let dbPort = config.get('db.port');
console.log(`Database port: ${dbPort}`);

let dbName = config.get('db.name');
console.log(`Database name: ${dbName}`);

console.log('NODE_ENV: ' + config.util.getEnv('NODE_ENV'));

$ node index.js
Application port: 3000
Database port: 27017
Database name: dev_db_name
NODE_ENV: development

For production
$ set NODE_ENV=production
$ node index.js
Application port: 4000
Database port: 27000
Database name: prod_db_name
NODE_ENV: production

其他回答

我的解决办法相当简单:

在./config/index.js中加载环境配置

var env = process.env.NODE_ENV || 'development'
  , cfg = require('./config.'+env);

module.exports = cfg;

在./config/config.global.js中定义一些默认值

var config = module.exports = {};

config.env = 'development';
config.hostname = 'dev.example.com';

//mongo database
config.mongo = {};
config.mongo.uri = process.env.MONGO_URI || 'localhost';
config.mongo.db = 'example_dev';

重写。/config/config.test.js中的默认值

var config = require('./config.global');

config.env = 'test';
config.hostname = 'test.example';
config.mongo.db = 'example_test';

module.exports = config;

在./models/user.js中使用:

var mongoose = require('mongoose')
, cfg = require('../config')
, db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);

在测试环境中运行应用程序:

NODE_ENV=test node ./app.js

现在,在使用数据库时,最简单的方法是完全不处理配置文件,因为部署环境更容易设置,只需使用单个环境变量(例如,将其称为DB_CONNECTION),并根据需要向其传递任何额外的配置数据。

配置数据举例:

const config = {
    userIds: [1, 2, 3],
    serviceLimit: 100,
    // etc., configuration data of any complexity    
};
// or you can read it from a config file

创建一个连接字符串,包含数据库驱动程序不关心的额外参数:

import {ConnectionString} from 'connection-string';

const cs = new ConnectionString('postgres://localhost@dbname', {
    user: 'user-name',
    password: 'my-password',
    params: {
        config
    }  ​
});

然后我们可以生成结果字符串存储在环境中:

cs.toString();
//=>postgres://localhost:my-password@dbname?config=%7B%22userIds%22%3A%5B1%2C2%2C3%5D%2C%22serviceLimit%22%3A100%7D

所以你把它存储在你的环境中,比如说DB_CONNECTION,在客户端进程中你可以通过process.env.DB_CONNECTION读取它:

const cs = new ConnectionString(process.env.DB_CONNECTION);

const config = JSON.parse(cs.params?.config); // parse extra configuration
//=> { userIds: [ 1, 2, 3 ], serviceLimit: 100 }

通过这种方式,您将在单个环境变量中同时拥有连接和所需的所有额外配置,而不需要打乱配置文件。

除了这个答案中提到的nconf模块,以及这个答案中提到的node-config模块,还有node-iniparser和IniReader,它们看起来更简单。ini配置文件解析器。

我最近刚刚发布了一个小模块来加载任何类型的配置文件。 它非常简单,你可以在https://github.com/flesler/config-node上查看

如何使用TypeScript。

export const loadConfig = () => {
    const configLoadeded = configLoader.util.toObject() as any
    Config = configLoadeded
}

export interface ConfigI {
    productName: string;
    productId: string;
    googleCloudApiKey: string;
}