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 ที่ต่างกัน

Qu ฉันจะตั้งค่าสิ่งเหล่านี้ในการกำหนดค่าสภาพแวดล้อมเพื่อกรองผ่านโมดูลทั้งหมดได้อย่างไรหรือฉันจะส่งเส้นทางไปยังโมดูลโดยตรงได้อย่างไร

ตั้งค่าใน 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();

จากนั้นเราสามารถเข้าถึงคุณสมบัติของวัตถุ config ได้เหมือนเดิม

conf.twitter.consumerKey

2
ทำไมคุณถึงใช้ใหม่ที่นี่?
bluehallu

5
ฉันสอง @bluehallu คือnewจำเป็น?
Sung Cho

2
สิ่งที่เทียบเท่าใน Windows จะเป็น SET NODE_ENV = development
mujaffars

3
แทนที่จะทำnew. ฉันติดตามในconfig.js....Config = function(){...}; module.exports = Config()
Atu

จะเกิดอะไรขึ้นถ้าฉันมีเว็บเซิร์ฟเวอร์ 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 } }
    }
}

สวัสดีคุณช่วยอธิบายได้ไหมว่าทำไมคุณถึงคิดว่านี่เป็นวิธีที่ดีกว่าในการแสดงการตั้งค่า (ซึ่งต่างจากการใช้สคริปต์ที่คืนค่าการตั้งค่า) ?
Venkat Kotra

14
ฉันเดาว่ามันไม่ได้สร้างความแตกต่างมากเกินไป ในใจเมื่อฉันเห็น JSON ฉันคิดว่า 'ข้อมูลคงที่' เทียบกับเมื่อฉันเห็นไฟล์ JS ฉันคิดว่ามีตรรกะบางอย่างอยู่ข้างใน นอกจากนี้ข้อดีอีกประการหนึ่งของการใช้ประเภท. json คือภาษาอื่น ๆ สามารถนำเข้าไฟล์เดียวกันได้
mattwad

1
การกำหนดค่า @VenkatKotra โดยทั่วไปถือว่าเป็นแบบคงที่ดังนั้นจึงแสดงออกได้ดีที่สุดด้วยสิ่งต่างๆเช่น json, yaml, ini ฯลฯ เสร็จสิ้นโดยมีความจำเป็นด้วยสคริปต์ที่ให้สถานะนั้น sortof หมายถึงบางสิ่งที่เกิดขึ้นแบบไดนามิกซึ่งจะไม่ดี
สูงสุด

9
โปรดทราบว่าวิธีนี้เปิดเผยข้อมูลประจำตัวในการควบคุมแหล่งที่มา
Pier-Luc Gendreau

ฉันสามารถสร้าง 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

หรือการตั้งค่าสภาพแวดล้อมที่ถูกต้องตลอดไปหรือ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 install config - ประหยัดไม่ดีกว่าเหรอ
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

ใน 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

อัปเดตสำหรับคำตอบนี้: สถาปนิกคือกรอบการจัดการการพึ่งพาที่แก้ไขปัญหานี้ด้วยวิธีที่ดีกว่า
ม.ค. Jongboom

5

วิธีที่สวยงามคือการใช้.envไฟล์เพื่อลบล้างการตั้งค่าการผลิตในเครื่อง ไม่จำเป็นต้องใช้สวิตช์บรรทัดคำสั่ง ไม่จำเป็นต้องใช้เครื่องหมายจุลภาคและวงเล็บทั้งหมดในconfig.jsonไฟล์ ดูคำตอบของฉันที่นี่

ตัวอย่าง: บนเครื่องของฉัน.envไฟล์คือ:

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

โลคัลของฉัน.envแทนที่ตัวแปรสภาพแวดล้อมใด ๆ แต่ในการแสดงละครหรือการผลิตเซิร์ฟเวอร์ (บางทีพวกเขากำลัง heroku.com) ตัวแปรสภาพแวดล้อมที่มีการตั้งไว้ไปยังขั้นตอนหรือการผลิตNODE_ENV=stageNODE_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 คุณต้องได้รับคอนฟิกูเรชันสภาพแวดล้อม "การพัฒนา" และใน 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] }

ฉันมักจะใช้ typescript ในโครงการโหนดของฉัน ด้านล่างนี้คือการคัดลอกวางการใช้งานจริงของฉัน

การใช้งาน 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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.