Node.js настраивает конфигурацию среды, специфичную для использования с everyauth

117

Я использую node.js + express.js + everyauth.js. Я переместил всю свою логику Everyauth в файл модуля

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

внутри я загружаю свой конфигурационный файл oAuth с комбинациями ключ / секрет:

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

Эти коды различны для разных сред - разработка / постановка / производство, поскольку обратные вызовы относятся к разным URL-адресам.

Королева Как мне установить их в конфигурации среды для фильтрации по всем модулям или я могу передать путь непосредственно в модуль?

Установить в env:

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'});
});

? надеюсь, что это имеет смысл

Энди т
источник
Нашел решение, в котором используются некоторые из идей, представленных ниже, имея модуль = функция, а не объект, я могу оценить process.env.NODE_ENV и вернуть правильный объект для среды. Немного грязно, но работает.
Энди Т
Простите за бесстыдную саморекламу, но я написал модуль для node.js, который будет делать это через отдельные файлы и переключатель командной строки: node-configure
Randolpho

Ответы:

192

Мое решение,

загрузить приложение, используя

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
Энди т
источник
2
Почему вы здесь используете новое?
bluehallu 01
5
Я второй @bluehallu. Является ли newнеобходимым?
Сунг Чо
2
эквивалент в Windows будет SET NODE_ENV = development
mujaffars
3
Вместо того, чтобы делать new. Я следую в config.js....Config = function(){...}; module.exports = Config()
Ату
Что, если у меня есть 50 веб-серверов, и в этом случае будет сложно перейти к каждому серверу, чтобы вручную
Раджеш
60

У вас также может быть файл JSON с NODE_ENV в качестве верхнего уровня. 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 } }
    }
}
mattwad
источник
Привет, не могли бы вы объяснить, почему вы думаете, что это лучший способ выразить настройки конфигурации (в отличие от использования скрипта, который возвращает настройки). ?
Венкат Котра,
14
Думаю, особой разницы в этом нет. Мысленно, когда я вижу JSON, я думаю, что это «статические данные», а когда я вижу файл JS, я думаю, что внутри него есть какая-то логика. Кроме того, еще одним преимуществом использования типа .json является то, что другие языки могут импортировать тот же файл.
Mattwad
1
Конфигурация @VenkatKotra обычно считается статической и поэтому лучше всего выражается декларативно с помощью таких вещей, как json, yaml, ini и т. Д. Совершенно императивно, со сценарием, который возвращает это состояние, sortof подразумевает, что происходит что- то динамическое , что было бы плохо.
максимум
9
Имейте в виду, что этот метод предоставляет учетные данные в системе управления версиями.
Пьер-Люк Жендро,
Могу ли я сделать другой URL для постановки и производства?
Alex
35

Очень полезное решение - использовать модуль конфигурации .

после установки модуля:

$ npm install config

Вы можете создать файл конфигурации default.json . (вы можете использовать объект JSON или JS с расширением .json5)

Например

$ 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
}

На вашем локальном ПК у вас может быть local.json, который переопределяет всю среду, или у вас может быть определенная локальная конфигурация как local-production.json или local-development.json .

Полный список порядка загрузки .

Внутри вашего приложения

В вашем приложении вам нужно только потребовать конфигурацию и необходимый атрибут.

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

Загрузите приложение

загрузите приложение, используя:

NODE_ENV=production node app.js

или установив правильную среду с помощью forever или pm2

Навсегда:

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

Это очень чистое решение, которое позволяет легко настраивать разные файлы конфигурации для среды производства / подготовки / разработки, а также для локальной настройки.

Zauker
источник
npm install config --save, не лучше?
stackdave
15

Вкратце

Такая установка проста и элегантна:

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/ , проверьте его для более детально.

крис
источник
5

Мы делаем это, передавая аргумент при запуске приложения с окружением. Например:

node app.js -c dev

Затем мы загружаем dev.jsв app.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.configure('developmentкода app.js , но посмотрю, смогу ли я использовать это решение с этим
andy t
Обновите этот ответ: Architect - это структура управления зависимостями, которая решает эту проблему лучше.
Ян Чонбум
5

Элегантный способ - использовать .envфайл для локального переопределения производственных настроек. Нет необходимости в переключателях командной строки. Нет необходимости во всех этих запятых и скобках в config.jsonфайле. Смотрите мой ответ здесь

Пример: на моей машине .envфайл такой:

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

Мой локальный .envпереопределяет любые переменные среды. Но на промежуточных или производственных серверах (возможно, они находятся на heroku.com) переменные среды предварительно настроены на этап NODE_ENV=stageили производство NODE_ENV=prod.

Benxamin
источник
4

установить переменную среды на сервере развертывания (например, как 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)

Удачного кодирования ...

Аджайкумар М.П.
источник
3

Как насчет того, чтобы сделать это более элегантным способом с помощью модуля nodejs-config .

Этот модуль может установить конфигурационную среду на основе имени вашего компьютера. После этого, когда вы запросите конфигурацию, вы получите значение для конкретной среды.

Например, предположим, что у вас есть две машины разработки с именами pc1 и pc2 и производственная машина с именем pc3. Когда вы когда-либо запрашиваете значения конфигурации в своем коде на pc1 или pc2, вы должны получить конфигурацию среды «разработки», а на pc3 вы должны получить конфигурацию среды «производственной». Этого можно добиться так:

  1. Создайте базовый файл конфигурации в каталоге config, скажем "app.json" и добавьте в него необходимые конфигурации.
  2. Теперь просто создайте папки в каталоге config, соответствующие имени вашей среды, в данном случае «разработка» и «производство».
  3. Затем создайте файлы конфигурации, которые вы хотите переопределить, и укажите параметры для каждой среды в каталогах среды (обратите внимание, что вам не нужно указывать все параметры, которые есть в базовом файле конфигурации, а только параметры, которые вы хотите переопределить. файлы конфигурации среды будут «каскадировать» по базовым файлам.).

Теперь создайте новый экземпляр конфигурации со следующим синтаксисом.

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

   }
);

Теперь вы можете получить любое значение конфигурации, не беспокоясь о такой среде:

config.get('app').configurationKey;
Хариш Анчу
источник
0

В этом ответе нет ничего нового. Это похоже на то, что упомянул @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] }

Обычно я использую машинописный текст в моем проекте узла. Ниже скопирована моя фактическая реализация.

Реализация машинописного текста

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)
Фарадж Фарук
источник