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

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

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


当前回答

另一个选项是为验证添加模式。像nconf一样,它支持从环境变量、参数、文件和json对象的任何组合中加载设置。

来自README的例子:

var convict = require('convict');
var conf = convict({
  env: {
    doc: "The applicaton environment.",
    format: ["production", "development", "test"],
    default: "development",
    env: "NODE_ENV"
  },
  ip: {
    doc: "The IP address to bind.",
    format: "ipaddress",
    default: "127.0.0.1",
    env: "IP_ADDRESS",
  },
  port: {
    doc: "The port to bind.",
    format: "port",
    default: 0,
    env: "PORT"
  }
});

入门文章: 用节点罪犯驯服构型

其他回答

你也可以看看dotenv,它遵循了十二要素应用程序的原则。

我曾经使用节点配置,但出于这个原因创建了dotenv。它的灵感完全来自ruby的dotenv库。

用法很简单:

var dotenv = require('dotenv');
dotenv.load();

然后你只需要创建一个。env文件,把你的设置放在那里,就像这样:

S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE
OTHER_SECRET_STUFF=my_cats_middle_name

这是nodejs的dotenv。

我的解决办法相当简单:

在./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

另一个选项是为验证添加模式。像nconf一样,它支持从环境变量、参数、文件和json对象的任何组合中加载设置。

来自README的例子:

var convict = require('convict');
var conf = convict({
  env: {
    doc: "The applicaton environment.",
    format: ["production", "development", "test"],
    default: "development",
    env: "NODE_ENV"
  },
  ip: {
    doc: "The IP address to bind.",
    format: "ipaddress",
    default: "127.0.0.1",
    env: "IP_ADDRESS",
  },
  port: {
    doc: "The port to bind.",
    format: "port",
    default: 0,
    env: "PORT"
  }
});

入门文章: 用节点罪犯驯服构型

在这里,我将全身心地投入其中,因为这些答案中没有一个解决了几乎任何系统都需要的所有关键组件。注意事项:

公共配置(可以从前端看到)vs私有配置(guy mograbi说对了)。并确保它们是分开的。 钥匙一样的秘密 默认值vs特定于环境的覆盖 前端包

以下是我如何进行配置:

config.default.private.js - In version control, these are default configuration options that can only be seen by your backend. config.default.public.js - In version control, these are default configuration options that can be seen by backend and frontend config.dev.private.js - If you need different private defaults for dev. config.dev.public.js - If you need different public defaults for dev. config.private.js - Not in version control, these are environment specific options that override config.default.private.js config.public.js - Not in version control, these are environment specific options that override config.default.public.js keys/ - A folder where each file stores a different secret of some kind. This is also not under version control (keys should never be under version control).

I use plain-old javascript files for configuration so I have the full power of the javascript langauge (including comments and the ability to do things like load the default config file in the environment-specific file so they can then be overridden). If you want to use environment variables, you can load them inside those config files (tho I recommend against using env vars for the same reason I don't recommend using json files - you don't have the power of a programming language to construct your config).

每个键在一个单独的文件中的原因是为了安装程序的使用。这允许您有一个安装程序,在机器上创建密钥并将它们存储在密钥文件夹中。如果不这样做,当你加载无法访问密钥的配置文件时,安装程序可能会失败。通过这种方式,您可以遍历目录并加载该文件夹中的任何关键文件,而不必担心在任何给定版本的代码中哪些存在哪些不存在。

由于您可能在私有配置中加载了密钥,因此您绝对不希望在任何前端代码中加载私有配置。虽然严格来说,将前端代码库与后端代码库完全分离可能更理想,但很多时候,PITA是一个足够大的障碍,阻止人们这样做,从而导致私有配置与公共配置。但是我做了两件事来防止在前端加载私有配置:

我有一个单元测试,确保我的前端包不包含我在私有配置中的一个密钥。 我将前端代码放在与后端代码不同的文件夹中,并且我有两个名为“config.js”的不同文件-一端一个。对于后端,config.js加载私有配置,对于前端,它加载公共配置。然后你总是只需要('config'),而不用担心它来自哪里。

最后一件事:您的配置应该通过一个完全独立于任何其他前端代码的文件加载到浏览器中。如果捆绑前端代码,公共配置应该作为一个完全独立的包构建。否则,你的配置就不再是真正的配置了——它只是你代码的一部分。配置需要能够在不同的机器上有所不同。

您还可以查看node-config,它根据$HOST和$NODE_ENV变量(有点像RoR)加载配置文件:文档。

这对于不同的部署设置(开发、测试或生产)非常有用。