Node.js menyiapkan konfigurasi khusus lingkungan untuk digunakan dengan everyauth

117

Saya menggunakan node.js + express.js + everyauth.js. Saya telah memindahkan semua logika everyauth saya ke dalam file modul

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

di dalamnya saya memuat file konfigurasi oAuth saya dengan kombinasi kunci / rahasia:

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

Kode-kode ini berbeda untuk lingkungan yang berbeda - pengembangan / pementasan / produksi karena callback ditujukan ke url yang berbeda.

Qu. Bagaimana cara mengaturnya di konfigurasi lingkungan untuk menyaring semua modul atau dapatkah saya meneruskan jalur langsung ke modul?

Diatur dalam env:

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

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

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

Masuk

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

? harap itu masuk akal

andy t
sumber
Menemukan solusi yang menggunakan beberapa ide dari bawah, dengan memiliki module = function daripada sebuah objek, saya dapat mengevaluasi process.env.NODE_ENV dan mengembalikan objek yang benar untuk lingkungan. Sedikit berantakan tapi berhasil.
andy t
Maaf atas promosi diri yang tidak tahu malu, tetapi saya menulis modul untuk node.js yang akan melakukan ini melalui file terpisah dan saklar baris perintah: node-configure
Randolpho

Jawaban:

192

Solusi saya,

memuat aplikasi menggunakan

NODE_ENV=production node app.js

Kemudian atur config.jssebagai fungsi, bukan sebagai objek

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

        case 'production':
            return {prod settings};

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

Kemudian sesuai dengan solusi Jans, muat file dan buat instance baru yang dapat kami berikan nilai jika diperlukan, dalam hal ini process.env.NODE_ENVbersifat global jadi tidak diperlukan.

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

Kemudian kita dapat mengakses properti objek config persis seperti sebelumnya

conf.twitter.consumerKey
andy t
sumber
2
Mengapa Anda menggunakan baru di sini?
bluehallu
5
Saya kedua @bluehallu. Apakah newperlu?
Sung Cho
2
padanan di Windows akan SET NODE_ENV = pengembangan
mujaffars
3
Daripada melakukan new. Saya mengikuti di config.js....Config = function(){...}; module.exports = Config()
Atu
Bagaimana jika saya memiliki 50 server web dalam hal ini akan sulit untuk pergi ke setiap server untuk memulai skrip secara manual
Rajesh
60

Anda juga dapat memiliki file JSON dengan NODE_ENV sebagai level teratas. IMO, ini adalah cara yang lebih baik untuk mengekspresikan pengaturan konfigurasi (sebagai lawan menggunakan skrip yang mengembalikan pengaturan).

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

Contoh untuk 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.dll
sumber
Hai, dapatkah Anda menjelaskan mengapa menurut Anda ini adalah cara yang lebih baik untuk mengekspresikan pengaturan konfigurasi (dibandingkan menggunakan skrip yang mengembalikan pengaturan). ?
Venkat Kotra
14
Saya kira itu tidak membuat banyak perbedaan. Secara mental, ketika saya melihat JSON saya pikir 'data statis' vs ketika saya melihat file JS, saya pikir ada beberapa logika di dalamnya. Selain itu, manfaat lain menggunakan jenis .json adalah bahasa lain dapat mengimpor file yang sama.
mattwad
1
Konfigurasi @VenkatKotra umumnya dianggap statis, dan oleh karena itu paling baik diekspresikan secara deklaratif dengan hal-hal seperti json, yaml, ini, dll. Dilakukan secara imperatif, dengan skrip yang menghasilkan status tersebut, sortof menyiratkan sesuatu yang dinamis sedang terjadi, yang akan menjadi buruk.
maks
9
Ketahuilah bahwa metode ini menampilkan kredensial di kontrol sumber.
Pier-Luc Gendreau
dapatkah saya membedakan url untuk pementasan dan produksi?
Alex
35

Solusi yang sangat berguna adalah menggunakan modul config .

setelah memasang modul:

$ npm install config

Anda dapat membuat file konfigurasi default.json . (Anda dapat menggunakan objek JSON atau JS menggunakan ekstensi .json5)

Sebagai contoh

$ vi config/default.json

{
  "name": "My App Name",
  "configPath": "/my/default/path",
  "port": 3000
}

Konfigurasi default ini dapat ditimpa oleh file konfigurasi lingkungan atau file konfigurasi lokal untuk lingkungan pengembangan lokal:

production.json bisa jadi:

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

development.json bisa jadi:

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

Di PC lokal Anda, Anda dapat memiliki local.json yang menggantikan semua lingkungan, atau Anda dapat memiliki konfigurasi lokal tertentu sebagai local-production.json atau local-development.json .

Daftar lengkap urutan pemuatan .

Di dalam Aplikasi Anda

Di aplikasi Anda, Anda hanya perlu memerlukan config dan atribut yang diperlukan.

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

Muat Aplikasi

memuat aplikasi menggunakan:

NODE_ENV=production node app.js

atau pengaturan lingkungan yang benar dengan forever atau pm2

Selama-lamanya:

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

PM2 (melalui shell):

export NODE_ENV=staging
pm2 start app.js

PM2 (melalui .json):

process.json

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

Lalu

$ pm2 start process.json --env production

Solusi ini sangat bersih dan memudahkan pengaturan file konfigurasi yang berbeda untuk lingkungan Produksi / Pementasan / Pengembangan dan untuk pengaturan lokal juga.

Zauker
sumber
npm install config --save, tidak lebih baik?
stackdave
15

Secara singkat

Jenis penyiapan ini sederhana dan elegan:

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

Untuk berjalan dalam mode produksi: $ NODE_ENV=production node app.js


Secara terperinci

Solusi ini dari: http://himanshu.gilani.info/blog/2012/09/26/bootstraping-a-node-dot-js-app-for-dev-slash-prod-environment/ , lihat untuk lebih detail.

keris
sumber
5

Cara kami melakukan ini adalah dengan memberikan argumen saat memulai aplikasi dengan lingkungan. Misalnya:

node app.js -c dev

Di app.js kami kemudian memuat dev.jssebagai file konfigurasi kami. Anda dapat mengurai opsi ini dengan optparse-js .

Sekarang Anda memiliki beberapa modul inti yang bergantung pada file konfigurasi ini. Ketika Anda menulisnya seperti itu:

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

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

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

Dan Anda dapat menyebutnya kemudian app.jsseperti:

var Workspace = require("workspace");
this.workspace = new Workspace(config);
Jan Jongboom
sumber
Saya lebih suka menyimpan semua logika di dalam app.configure('developmentkode app.js , tetapi akan melihat apakah saya dapat menggunakan solusi ini dengan itu
andy t
Perbarui jawaban ini: Arsitek adalah kerangka kerja manajemen ketergantungan yang menyelesaikan ini dengan cara yang lebih baik.
Jan Jongboom
5

Cara yang elegan adalah menggunakan .envfile untuk mengganti pengaturan produksi secara lokal. Tidak perlu sakelar baris perintah. Tidak perlu semua koma dan tanda kurung dalam sebuah config.jsonfile. Lihat jawaban saya di sini

Contoh: di komputer saya, .envfile tersebut adalah:

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

Lokal saya .envmenimpa variabel lingkungan apa pun. Namun di server pementasan atau produksi (mungkin mereka ada di heroku.com), variabel lingkungan sudah disetel sebelumnya ke tahap NODE_ENV=stageatau produksi NODE_ENV=prod.

Benxamin
sumber
4

setel variabel lingkungan di server penerapan (mis .: seperti NODE_ENV = produksi). Anda dapat mengakses variabel lingkungan Anda melalui process.env.NODE_ENV. Temukan file konfigurasi berikut untuk pengaturan global

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 : '[email protected]',
    },
    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 berisi konfigurasi umum untuk semua lingkungan.

lalu impor di modul lain seperti

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

Selamat Coding ...

ajaykumar mp
sumber
3

Bagaimana kalau melakukan ini dengan cara yang jauh lebih elegan dengan modul nodejs-config .

Modul ini dapat mengatur lingkungan konfigurasi berdasarkan nama komputer Anda. Setelah itu ketika Anda meminta konfigurasi, Anda akan mendapatkan nilai spesifik lingkungan.

Sebagai contoh mari kita asumsikan Anda memiliki dua mesin pengembangan bernama pc1 dan pc2 dan mesin produksi bernama pc3. Setiap kali Anda meminta nilai konfigurasi dalam kode Anda di pc1 atau pc2, Anda harus mendapatkan konfigurasi lingkungan "pengembangan" dan di pc3 Anda harus mendapatkan konfigurasi lingkungan "produksi". Ini bisa dicapai seperti ini:

  1. Buat file konfigurasi dasar di direktori config, katakanlah "app.json" dan tambahkan konfigurasi yang diperlukan ke dalamnya.
  2. Sekarang cukup buat folder di dalam direktori config yang sesuai dengan nama lingkungan Anda, dalam hal ini "pengembangan" dan "produksi".
  3. Selanjutnya, buat file konfigurasi yang ingin Anda timpa dan tentukan opsi untuk setiap lingkungan di direktori lingkungan (Perhatikan bahwa Anda tidak harus menentukan setiap opsi yang ada di file konfigurasi dasar, tetapi hanya opsi yang ingin Anda timpa. file konfigurasi lingkungan akan "mengalir" di atas file dasar.).

Sekarang buat instance konfigurasi baru dengan sintaks berikut.

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

   }
);

Sekarang Anda bisa mendapatkan nilai konfigurasi apa pun tanpa mengkhawatirkan lingkungan seperti ini:

config.get('app').configurationKey;
Harish Anchu
sumber
0

Jawaban ini bukanlah sesuatu yang baru. Ini mirip dengan apa yang @andy_t sebutkan. Tetapi saya menggunakan pola di bawah ini karena dua alasan.

  1. Implementasi bersih tanpa ketergantungan npm eksternal

  2. Gabungkan pengaturan konfigurasi default dengan pengaturan berbasis lingkungan.

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

Saya biasanya menggunakan skrip dalam proyek node saya. Di bawah ini adalah implementasi copy-paste saya yang sebenarnya.

Implementasi skrip ketikan

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)
Faraj Farook
sumber