Node.js налаштовує специфічні конфігурації для середовища, які будуть використані з кожним auth


117

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

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 і повернути правильний об'єкт для середовища. Трохи безладно, але працює.
andy t

Вибачте за безсоромне саморекламування, але я написав модуль для 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

5
Я другий @bluehallu. Чи newпотрібно?
Сун Чо

2
еквівалент у Windows буде SET NODE_ENV = розробка
mujaffars

3
Замість того, щоб робити new. Я config.jsConfig = function(){...}; module.exports = Config()
слідую

Що робити, якщо у мене є 50 веб-серверів, і в цьому випадку буде важко перейти на кожен сервер, щоб вручну ініціювати сценарій
Rajesh

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

Привіт, ви можете пояснити, чому ви вважаєте, що це кращий спосіб виразити налаштування конфігурації (на відміну від використання сценарію, який повертає налаштування). ?
Венкат Котра

14
Я думаю, це не має великої різниці. Подумки, коли я бачу JSON, я думаю, що "статичні дані" проти, коли я бачу файл JS, я думаю, що в ньому є певна логіка. Крім того, ще одна перевага використання типу .json полягає в тому, що інші мови можуть імпортувати той самий файл.
mattwad

1
Конфігурація @VenkatKotra, як правило, вважається статичною, і тому найкраще виражається декларативно з такими речами, як json, yaml, ini тощо. Виконано в обов'язковому порядку зі сценарієм, який дає такий стан, sortof передбачає, що відбувається щось динамічне , що було б погано.
макс

9
Майте на увазі, що цей метод викриває дані щодо контролю джерел.
П’єр-Люк Джендро

Чи можу я зробити URL-адресу різниці для постановки та виробництва?
Олексій

34

Дуже корисним рішенням є використання конфігураційного модуля .

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

$ 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

або налаштування правильного середовища назавжди або 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

Це рішення є дуже чистим і дозволяє легко встановлювати різні конфігураційні файли для середовища виробництва / постановки / розробки та для локальних параметрів.


npm встановити config - зберегти, це не краще?
stackdave

14

Коротко

Цей тип налаштування простий та елегантний:

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

Потім у 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.configure('developmentкоду app.js , але буду дивитись, чи зможу я використовувати це рішення з цим
andy t

Оновлення до цієї відповіді: Архітектор - це система управління залежністю, яка вирішує це набагато приємніше.
Ян Ченгум

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.


4

встановити змінну середовища на сервері розгортання (наприклад: як NODE_ENV = виробництво). Ви можете отримати доступ до змінної навколишнього середовища через 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;

база містить загальну конфігурацію для всіх середовищ.

потім імпортуйте в інші модулі, як-от

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

Щасливе кодування ...


3

Як щодо цього зробити набагато більш елегантно з модулем nodejs-config .

Цей модуль може встановити середовище конфігурації залежно від імені вашого комп'ютера. Після цього, коли ви запитаєте конфігурацію, ви отримаєте значення середовища.

Наприклад, припустимо, у вас є дві розроблювальні машини з назвою pc1 та pc2 та виробнича машина з назвою pc3. Коли ви коли-небудь запитуєте значення конфігурації у своєму коді в pc1 або pc2, ви повинні отримати конфігурацію середовища "development", а в pc3 ви повинні отримати конфігурацію середовища "виробництво". Цього можна досягти так:

  1. Створіть базовий файл конфігурації у конфігураційному каталозі, скажімо "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;

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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.