【问题标题】:Node.js setting up environment specific configs to be used with everyauthNode.js 设置与everyauth 一起使用的环境特定配置
【发布时间】:2012-01-10 01:35:06
【问题描述】:

我正在使用 node.js + express.js +everyauth.js。我已将所有的everyauth 逻辑移到一个模块文件中

var login = require('./lib/everyauthLogin');

在其中我使用密钥/秘密组合加载我的 oAuth 配置文件:

var conf = require('./conf');
.....
twitter: {
    consumerKey: 'ABC', 
    consumerSecret: '123'
}

这些代码对于不同的环境是不同的 - 开发/登台/生产,因为回调是不同的 url。

问题:如何在环境配置中设置这些以过滤所有模块,或者我可以将路径直接传递到模块中吗?

在环境中设置:

app.configure('development', function(){
  app.set('configPath', './confLocal');
});

app.configure('production', function(){
  app.set('configPath', './confProduction');
});

var conf = require(app.get('configPath'));

传入

app.configure('production', function(){
  var login = require('./lib/everyauthLogin', {configPath: './confProduction'});
});

?希望这是有道理的

【问题讨论】:

  • 找到了一个使用下面一些想法的解决方案,通过使用 module = function 而不是我可以评估 process.env.NODE_ENV 并返回环境的正确对象的对象。有点凌乱但有效。
  • 请原谅无耻的自我推销,但我为 node.js 编写了一个模块,它将通过单独的文件和命令行开关来做到这一点:node-configure

标签: node.js environment-variables everyauth


【解决方案1】:

我们这样做的方式是在使用环境启动应用程序时传入一个参数。例如:

node app.js -c dev

然后我们在 app.js 中加载 dev.js 作为我们的配置文件。您可以使用optparse-js 解析这些选项。

现在你有了一些依赖于这个配置文件的核心模块。当你这样写它们时:

var Workspace = module.exports = function(config) {
    if (config) {
         // do something;
    }
}

(function () {
    this.methodOnWorkspace = function () {

    };
}).call(Workspace.prototype);

然后您可以在app.js 中调用它,例如:

var Workspace = require("workspace");
this.workspace = new Workspace(config);

【讨论】:

  • 我宁愿将所有逻辑保留在 app.js app.configure('development 代码中,但会看看我是否可以使用这个解决方案
  • 更新到这个答案:Architect 是一个依赖管理框架,可以更好地解决这个问题。
【解决方案2】:

我的解决方案,

使用加载应用程序

NODE_ENV=production node app.js

然后将config.js 设置为函数而不是对象

module.exports = function(){
    switch(process.env.NODE_ENV){
        case 'development':
            return {dev setting};

        case 'production':
            return {prod settings};

        default:
            return {error or other settings};
    }
};

然后根据 Jans 解决方案加载文件并创建一个新实例,如果需要,我们可以传入一个值,在这种情况下,process.env.NODE_ENV 是全局的,因此不需要。

var Config = require('./conf'),
    conf = new Config();

然后我们可以像以前一样访问配置对象属性

conf.twitter.consumerKey

【讨论】:

  • 你为什么在这里使用新的?
  • 我第二个@bluehallu。 new 有必要吗?
  • Windows 中的等价物是 SET NODE_ENV=development
  • 而不是new。我关注config.js ....Config = function(){...}; module.exports = Config()
  • 如果我有 50 个 Web 服务器怎么办,在这种情况下很难继续到每个服务器手动启动脚本
【解决方案3】:

您还可以拥有一个以 NODE_ENV 作为顶层的 JSON 文件。 IMO,这是表达配置设置的更好方法(而不是使用返回设置的脚本)。

var config = require('./env.json')[process.env.NODE_ENV || 'development'];

env.json 示例:

{
    "development": {
        "MONGO_URI": "mongodb://localhost/test",
        "MONGO_OPTIONS": { "db": { "safe": true } }
    },
    "production": {
        "MONGO_URI": "mongodb://localhost/production",
        "MONGO_OPTIONS": { "db": { "safe": true } }
    }
}

【讨论】:

  • 您好,您能否解释一下为什么您认为这是表达配置设置的更好方式(而不是使用返回设置的脚本)。 ?
  • 我想这并没有太大的区别。在心理上,当我看到 JSON 时,我认为是“静态数据”,而当我看到 JS 文件时,我认为其中有一些逻辑。此外,使用 .json 类型的另一个好处是其他语言可以导入相同的文件。
  • @VenkatKotra 配置通常被认为是静态的,因此最好用 json、yaml、ini 等以声明方式表示。命令式地完成,使用产生该状态的脚本,sortof 暗示了一些 动态 正在发生,这会很糟糕。
  • 请注意,此方法会在源代码管理中公开凭据。
  • 我可以制作不同的 url 用于暂存和生产吗?
【解决方案4】:

如何使用nodejs-config 模块以更优雅的方式执行此操作。

此模块可以根据您的计算机名称设置配置环境。之后,当您请求配置时,您将获得特定于环境的值。

例如,假设您有两台名为 pc1 和 pc2 的开发机器和一台名为 pc3 的生产机器。当您在 pc1 或 pc2 的代码中请求配置值时,您必须获得“开发”环境配置,而在 pc3 中,您必须获得“生产”环境配置。可以这样实现:

  1. 在 config 目录中创建一个基本配置文件,让我们说“app.json”并向其中添加所需的配置。
  2. 现在只需在配置目录中创建与您的环境名称匹配的文件夹,在本例中为“开发”和“生产”。
  3. 接下来,创建您希望覆盖的配置文件,并在环境目录中为每个环境指定选项(请注意,您不必指定基本配置文件中的每个选项,只需指定您希望的选项覆盖。环境配置文件将“级联”在基础文件之上。)。

现在使用以下语法创建新的配置实例。

var config = require('nodejs-config')(
   __dirname,  // an absolute path to your applications 'config' directory
   {
      development: ["pc1", "pc2"],
      production: ["pc3"],

   }
);

现在你可以得到任何配置值而不用担心这样的环境:

config.get('app').configurationKey;

【讨论】:

    【解决方案5】:

    一种优雅的方法是使用.env 文件在本地覆盖生产设置。 不需要命令行开关。 config.json 文件中不需要所有这些逗号和括号。 See my answer here

    示例:在我的机器上,.env 文件是这样的:

    NODE_ENV=dev
    TWITTER_AUTH_TOKEN=something-needed-for-api-calls
    

    我的本​​地 .env 会覆盖所有环境变量。但在暂存或生产服务器上(可能在 heroku.com 上),环境变量已预先设置为暂存 NODE_ENV=stage 或生产 NODE_ENV=prod

    【讨论】:

      【解决方案6】:

      一个非常有用的解决方案是使用config module

      安装模块后:

      $ npm install config
      

      您可以创建一个 default.json 配置文件。 (您可以使用扩展名为 .json5 的 JSON 或 JS 对象)

      例如

      $ vi config/default.json
      
      {
        "name": "My App Name",
        "configPath": "/my/default/path",
        "port": 3000
      }
      

      此默认配置可以被环境配置文件或本地开发环境的本地配置文件覆盖:

      production.json 可以是:

      {
        "configPath": "/my/production/path",
        "port": 8080
      }
      

      development.json 可能是:

      {
        "configPath": "/my/development/path",
        "port": 8081
      }
      

      在您的本地 PC 中,您可以有一个覆盖所有环境的 local.json,或者您可以有一个特定的本地配置,如 local-production.jsonlocal-development.json.

      完整的list of load order

      在您的应用中

      在您的应用中,您只需要 require config 和 required 属性。

      var conf = require('config'); // it loads the right file
      var login = require('./lib/everyauthLogin', {configPath: conf.get('configPath'));
      

      加载应用

      使用以下方式加载应用程序:

      NODE_ENV=production node app.js
      

      或使用 foreverpm2

      设置正确的环境

      永远:

      NODE_ENV=production forever [flags] start app.js [app_flags]
      

      PM2(通过外壳):

      export NODE_ENV=staging
      pm2 start app.js
      

      PM2(通过 .json):

      process.json

      {
         "apps" : [{
          "name": "My App",
          "script": "worker.js",
          "env": {
            "NODE_ENV": "development",
          },
          "env_production" : {
             "NODE_ENV": "production"
          }
        }]
      }
      

      然后

      $ pm2 start process.json --env production
      

      这个解决方案非常干净,它可以轻松地为生产/暂存/开发环境和本地设置设置不同的配置文件。

      【讨论】:

      • npm install config --save ,不是更好吗?
      【解决方案7】:

      简述

      这种设置简单而优雅:

      env.json

      {
        "development": {
            "facebook_app_id": "facebook_dummy_dev_app_id",
            "facebook_app_secret": "facebook_dummy_dev_app_secret",
        }, 
        "production": {
            "facebook_app_id": "facebook_dummy_prod_app_id",
            "facebook_app_secret": "facebook_dummy_prod_app_secret",
        }
      }
      

      common.js

      var env = require('env.json');
      
      exports.config = function() {
        var node_env = process.env.NODE_ENV || 'development';
        return env[node_env];
      };
      

      app.js

      var common = require('./routes/common')
      var config = common.config();
      
      var facebook_app_id = config.facebook_app_id;
      // do something with facebook_app_id
      

      在生产模式下运行: $ NODE_ENV=production node app.js


      详细说明

      此解决方案来自:http://himanshu.gilani.info/blog/2012/09/26/bootstraping-a-node-dot-js-app-for-dev-slash-prod-environment/,详情请查看。

      【讨论】:

        【解决方案8】:

        这个答案并不是什么新鲜事。这与@andy_t 提到的类似。但我使用以下模式有两个原因。

        1. 干净的实现,没有外部 npm 依赖项

        2. 将默认配置设置与基于环境的设置合并。

        Javascript 实现

        const settings = {
            _default: {
               timeout: 100
               baseUrl: "http://some.api/",
            },
            production: {
               baseUrl: "http://some.prod.api/",
            },
        }
        // If you are not using ECMAScript 2018 Standard
        // https://stackoverflow.com/a/171256/1251350
        module.exports = { ...settings._default, ...settings[process.env.NODE_ENV] }
        

        我通常在我的节点项目中使用打字稿。下面是我实际复制粘贴的实现。

        Typescript 实现

        const settings: { default: ISettings, production: any } = {
            _default: {
                timeout: 100,
                baseUrl: "",
            },
            production: {
                baseUrl: "",
            },
        }
        
        export interface ISettings {
            baseUrl: string
        }
        
        export const config = ({ ...settings._default, ...settings[process.env.NODE_ENV] } as ISettings)
        

        【讨论】:

          【解决方案9】:

          在部署服务器中设置环境变量(例如:像 NODE_ENV=production)。您可以通过 process.env.NODE_ENV 访问您的环境变量。 找到以下全局设置的配置文件

          const env = process.env.NODE_ENV || "development"
          
          const configs = {
              base: {
                  env,
                  host: '0.0.0.0',
                  port: 3000,
                  dbPort: 3306,
                  secret: "secretKey for sessions",
                  dialect: 'mysql',
                  issuer : 'Mysoft corp',
                  subject : 'some@user.com',
              },
              development: {
                  port: 3000,
                  dbUser: 'root',
                  dbPassword: 'root',
          
              },
              smoke: {
                  port: 3000,
                  dbUser: 'root',
              },
              integration: {
                  port: 3000,
                  dbUser: 'root',
              },
              production: {
                  port: 3000,
                  dbUser: 'root',
              }
          };
          
          const config = Object.assign(configs.base, configs[env]);
          
          module.exports= config;
          

          “base”包含所有环境的通用配置。

          然后导入其他模块,如:

          const config =  require('path/to/config.js')
          console.log(config.port)
          

          快乐编码...

          【讨论】:

          • 这应该被 git 忽略吧,因为它包含敏感信息?如果忽略此文件,那么如何在部署期间包含此文件?
          • 这是一个非常好的问题,在这种情况下,您可以将环境特定的文件存储在相应的服务器中。然后在部署时从本地服务器中提取配置。
          猜你喜欢
          • 2017-12-08
          • 2018-01-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-16
          • 2014-04-25
          • 2012-09-17
          • 1970-01-01
          相关资源
          最近更新 更多