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

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

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


当前回答

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

公共配置(可以从前端看到)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'),而不用担心它来自哪里。

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

其他回答

你们使用npm来启动你的脚本(env等)吗?

如果你使用.env文件,你可以将它们包含在package.json中 并使用NPM来源/启动它们。

例子:

{
  "name": "server",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node test.js",
    "start-dev": "source dev.env; node test.js",
    "start-prod": "source prod.env; node test.js"
  },
  "dependencies": {
    "mysql": "*"
  }
}

然后运行NPM脚本:

$ npm start-dev

描述在这里https://gist.github.com/ericelliott/4152984 这都要归功于埃里克·埃利奥特

您可以将Konfig用于特定于环境的配置文件。它自动加载json或yaml配置文件,它有默认值和动态配置功能。

Konfig repo的一个例子:

File: config/app.json
----------------------------
{
    "default": {
        "port": 3000,
        "cache_assets": true,
        "secret_key": "7EHDWHD9W9UW9FBFB949394BWYFG8WE78F"
    },

    "development": {
        "cache_assets": false
    },

    "test": {
        "port": 3001
    },

    "staging": {
        "port": #{process.env.PORT},
        "secret_key": "3F8RRJR30UHERGUH8UERHGIUERHG3987GH8"
    },

    "production": {
        "port": #{process.env.PORT},
        "secret_key": "3F8RRJR30UHERGUH8UERHGIUERHG3987GH8"
    }
}

在发展:

> config.app.port
3000

在生产环境中,假设我们使用$ NODE_ENV=生产PORT=4567节点app.js启动应用程序

> config.app.port
4567

详情:https://github.com/vngrs/konfig

我将创建一个文件夹,配置一个命名为config.js的文件,稍后我会在需要的地方使用这个文件,如下所示

config.js的例子

module.exports = {
    proxyURL: 'http://url:port',
    TWITTER: {
        consumerkey: 'yourconsumerkey',
        consumerSecrete: 'yourconsumersecrete'
    },
    GOOGLE: {
        consumerkey: 'yourconsumerkey',
        consumerSecrete: 'yourconsumersecrete'
    },
    FACEBOOK: {
        consumerkey: 'yourconsumerkey',
        consumerSecrete: 'yourconsumersecrete'
    }
}

然后,如果我想在某处使用这个配置文件

我将首先导入如下

Var config = require('./config');

,我可以访问如下的值

const oauth = OAuth({
    consumer: {
        key: config.TWITTER.consumerkey,
        secret: config.TWITTER.consumerSecrete
    },
    signature_method: 'HMAC-SHA1',
    hash_function(base_string, key) {
        return crypto.createHmac('sha1', key).update(base_string).digest('base64');
    }
});

有点晚了(只有10年),但我使用的config.js结构如下:

const env = process.env.NODE_ENV || 'development';

var config_temp = {
    default:{
        port: 3000,
        mysql_host: "localhost",
        logging_level: 5,
        secret_api_key: process.env.SECRET_API_KEY
    },
    development: {
        logging_level: 10
    },
    production: {
        port: 3001,
        mysql_host: "not-localhost"
    }
};
var config = {
    ...config_temp.default, 
    ...config_temp[env]
}
module.exports = config;

然后我加载配置:

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

这样:

env变量的读取包含在config.js文件中,因此我可以避免这种丑陋的情况:NODE_ENV || 'development']。 config.js文件可以在代码的repo中上传,因为敏感变量继续由process.env处理。 如果default:{和custom_env:{中都包含同一个元素,则只保留第二个元素。 没有专用文件夹和多个文件(像在配置中)

我知道这是一个非常老的帖子。但是我想分享我的配置环境变量的模块,我认为这是一个非常灵活的解决方案。 下面是模块json-configurator

var configJson = {
  'baseUrl': 'http://test.com',
  '$prod_baseUrl': 'https://prod.com',
  'endpoints': {
    'users': '<%= baseUrl %>/users',
    'accounts': '<%= baseUrl %>/accounts'
    },
  foo: 'bar',
  foobar: 'foobar',
  $prod_foo: 'foo in prod',
  $test_foo: 'foo in test',
  deep:{
    veryDeep: {
      publicKey: 'abc',
      secret: 'secret',
      $prod_secret: 'super secret'
    }
  }
};

var config = require('json-configurator')(configJson, 'prod');

console.log(config.deep.veryDeep.secret) 
// super secret 

console.log(config.endpoints.users)
// https://prod.com/users 

然后你可以使用process.env。NODE_ENV来获取环境的所有变量。