Bagaimana cara menyimpan pengaturan / konfigurasi file pengaturan Node.js?

640

Saya telah bekerja pada beberapa aplikasi Node, dan saya telah mencari pola yang baik untuk menyimpan pengaturan terkait penempatan. Di dunia Django (dari mana saya berasal), praktik umum adalah memiliki settings.pyfile yang berisi pengaturan standar (zona waktu, dll), dan kemudian local_settings.pyuntuk pengaturan spesifik penempatan, yaitu. database apa yang harus diajak bicara, soket memcache apa, alamat email untuk admin dan sebagainya.

Saya telah mencari pola serupa untuk Node. Hanya file config yang bagus, jadi tidak harus macet dengan yang lainnya app.js, tetapi saya merasa penting untuk memiliki cara untuk memiliki konfigurasi khusus server dalam file yang tidak ada dalam kontrol sumber. Aplikasi yang sama bisa digunakan di server yang berbeda dengan pengaturan yang sangat berbeda, dan harus berurusan dengan menggabungkan konflik dan semua itu bukan ide saya yang menyenangkan.

Jadi apakah ada semacam kerangka / alat untuk ini, atau apakah semua orang hanya meretas sesuatu bersama?

mikl
sumber
saya benar-benar seperti cara konfigurasi dilakukan di mean.js . pada dasarnya, mereka menyimpan konfigurasi aplikasi yang relevan dalam semacam modul terpisah, berdasarkan pada pengaturan berbeda per lingkungan aplikasi (untuk produksi, pengembangan, pengujian) dan meneruskan detail spesifik melalui variabel lingkungan aplikasi, seperti rahasia dll.
Hinrich

Jawaban:

765

Saya menggunakan a package.jsonuntuk paket saya dan config.jsuntuk konfigurasi saya, yang terlihat seperti:

var config = {};

config.twitter = {};
config.redis = {};
config.web = {};

config.default_stuff =  ['red','green','blue','apple','yellow','orange','politics'];
config.twitter.user_name = process.env.TWITTER_USER || 'username';
config.twitter.password=  process.env.TWITTER_PASSWORD || 'password';
config.redis.uri = process.env.DUOSTACK_DB_REDIS;
config.redis.host = 'hostname';
config.redis.port = 6379;
config.web.port = process.env.WEB_PORT || 9980;

module.exports = config;

Saya memuat konfigurasi dari proyek saya:

var config = require('./config');

dan kemudian saya dapat mengakses barang-barang saya dari config.db_host,, config.db_portdll ... Ini memungkinkan saya menggunakan parameter hardcoded, atau parameter yang disimpan dalam variabel lingkungan jika saya tidak ingin menyimpan kata sandi dalam kontrol sumber.

Saya juga membuat package.jsondan memasukkan bagian dependensi:

"dependencies": {
  "cradle": "0.5.5",
  "jade": "0.10.4",
  "redis": "0.5.11",
  "socket.io": "0.6.16",
  "twitter-node": "0.0.2",
  "express": "2.2.0"
}

Ketika saya mengkloning proyek ke mesin lokal saya, saya menjalankan npm installuntuk menginstal paket. Info lebih lanjut tentang itu di sini .

Proyek disimpan di GitHub, dengan remote ditambahkan untuk server produksi saya.

noli
sumber
32
apa yang terjadi ketika Anda memiliki pengaturan konfigurasi berbeda untuk dev vs prod?
chovy
4
Saya belum tetapi di sini satu cara untuk melakukannya .. untuk setiap env, atur nama env dalam variabel ENV. Kemudian dalam file ini, itu hanya javascript .. menggunakan kasus atau jika pernyataan untuk memuat variabel yang sesuai. Anda bahkan dapat membuat subfile config terpisah untuk setiap env, dan dalam pernyataan if, muat ulang subfile di sini ke dalam subkonfig, dan ekspor subkonfig tersebut ke konfigurasi utama .. Semua yang saya coba katakan pada dasarnya adalah hanya js, jadi kamu bisa kreatif
noli
4
proses apa. env? dimana lokasinya? Dan bagaimana cara mengaturnya?
Kiwi
12
Saya berpikir "wow .. saya telah melihat node.js selama beberapa jam dan aplikasi saya sudah berfungsi .. btw, mungkin saya akan membagikan sedikit kode acak yang saya buat"
noli
3
Tidak bisakah Anda masih menggunakan variabel lingkungan untuk menyimpan kata-kata sandi itu? Bukankah itu maksud dari baris ini: config.twitter.password = process.env.TWITTER_PASSWORD || 'kata sandi';
DMart
244

Anda dapat meminta file JSON sejak Node v0.5.x ( merujuk jawaban ini )

config.json:

{
    "username" : "root",
    "password" : "foot"
}

app.js:

var config = require('./config.json');
log_in(config.username, config.password);
TinyTimZamboni
sumber
40
Tidak begitu terkesan dengan fitur itu. Anda bisa meminta ("./ config.js") dan Anda mendapatkan kemampuan untuk menambahkan komentar ke file konfigurasi yang saya anggap sangat penting, dan lonceng dan peluit lainnya. Jika Anda hanya
mengonfigurasi
3
@teknopaul Anda benar tetapi dulu ada diskusi besar tentang 'kebenaran' / kegunaan menggunakan sistem templating bodoh vs pintar yang mengatakan kepada saya: (1) Anda biasanya menginginkan bahasa deklaratif / bodoh untuk templating / opsi (2) itu ide buruk untuk merekonstruksi "hampir-PL" untuk hanya melakukan templating (atau konfigurasi) - lebih baik untuk menggunakan kembali PL nyata Anda yang ada dengan perilaku yang dikenal. sejauh ini +1 untuk mendaur ulang JS untuk melakukan pengaturan pengguna; -1 untuk tidak menggunakan pendekatan deklaratif. kami telah melihat beberapa hal konfigurasi yang cukup rumit dilakukan dengan cara deklaratif; nyali saya mengatakan ini adalah cara untuk pergi.
mengalir
1
Tidak ada intellisense pada objek dari file json di VScode (akhir 2017). Intellisense berfungsi penuh untuk objek dari module.exports.
Romain Vincent
199

Jauh kemudian, saya menemukan modul Node.js yang cukup bagus untuk mengelola konfigurasi: nconf .

Contoh sederhana:

var nconf = require('nconf');

// First consider commandline arguments and environment variables, respectively.
nconf.argv().env();

// Then load configuration from a designated file.
nconf.file({ file: 'config.json' });

// Provide default values for settings not provided above.
nconf.defaults({
    'http': {
        'port': 1337
    }
});

// Once this is in place, you can just use nconf.get to get your settings.
// So this would configure `myApp` to listen on port 1337 if the port
// has not been overridden by any of the three configuration inputs
// mentioned above.
myApp.listen(nconf.get('http:port'));

Ini juga mendukung pengaturan penyimpanan di Redis , menulis file konfigurasi, dan memiliki API yang cukup solid, dan juga didukung oleh salah satu toko Node.js yang lebih dihormati, Nodejitsu , sebagai bagian dari Flatiron inisiatif kerangka kerja , jadi seharusnya cukup bukti di masa depan.

Lihat nconf di Github .

mikl
sumber
2
Mungkin pertanyaan bodoh tapi saya belum melihat penjelasan yang jelas: Di mana saya mengatur variabel environment node? Saya sudah menggunakan nconf tetapi tidak jelas di mana saya akan mengatur variabel lingkungan. Apakah itu di nginx / apache? Apakah ini file konfigurasi lain?
Sipil
91
Saya tidak berpikir menggunakan file .json sebagai config adalah ide yang bagus, karena komentar tidak diperbolehkan.
Frank Xu
11
Ini terlihat hebat. Saya pikir Anda akan mengejutkan banyak Unixheads jika file konfigurasi mengabaikan opsi baris perintah dan variabel lingkungan. Kami sudah terbiasa dengan urutan naik prioritas: file config, variabel lingkungan, opsi baris perintah.
sheldonh
2
@sheldonh Tunggu sampai Anda mengetahui bahwa opsi boolean selalu diset pada argv, karena itu melanggar prioritas ...: /
Daniel C. Sobral
@ DanielC.Sobral Ini benar-benar memalukan. Oh, dan LTNS! :-)
sheldonh
94

Solusi saya cukup sederhana:

Memuat konfigurasi lingkungan ./config/index.js

var env = process.env.NODE_ENV || 'development'
  , cfg = require('./config.'+env);

module.exports = cfg;

Tetapkan beberapa default di ./config/config.global.js

var config = module.exports = {};

config.env = 'development';
config.hostname = 'dev.example.com';

//mongo database
config.mongo = {};
config.mongo.uri = process.env.MONGO_URI || 'localhost';
config.mongo.db = 'example_dev';

Timpa default di ./config/config.test.js

var config = require('./config.global');

config.env = 'test';
config.hostname = 'test.example';
config.mongo.db = 'example_test';

module.exports = config;

Menggunakannya di ./models/user.js:

var mongoose = require('mongoose')
, cfg = require('../config')
, db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);

Menjalankan aplikasi Anda di lingkungan pengujian:

NODE_ENV=test node ./app.js
kenyal
sumber
2
Saya lebih suka yang ini. Seperti yang disebutkan oleh orang lain JSON bukan struktur penyimpanan yang disukai dan pelapisan dengan global ini sederhana & efektif
Sebastian J.
Satu-satunya alasan saya lebih suka ini daripada nconf adalah karena memungkinkan format .js untuk file config (dev, test dan prod). memungkinkan kami untuk mendokumentasikan setiap opsi konfigurasi yang jika tidak dimungkinkan dengan format JSON.
Kunal Kapadia
BTW, NODE_ENVstandarnya adalah 'pengembangan'. Anda harus memeriksa 'produksi' sebagai gantinya.
Kevin Suttle
5
Saya tidak memeriksa pengembangan. Saya default-nya. Tidak yakin mengapa saya akan default untuk produksi.
chovy
39

Anda mungkin juga mencari dotenv yang mengikuti prinsip aplikasi dua belas faktor .

Saya dulu menggunakan node-config, tetapi menciptakan dotenv karena alasan itu. Itu benar-benar terinspirasi oleh perpustakaan dotenv ruby.

Penggunaannya cukup mudah:

var dotenv = require('dotenv');
dotenv.load();

Kemudian Anda hanya membuat file .env dan meletakkan pengaturan Anda di sana seperti:

S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE
OTHER_SECRET_STUFF=my_cats_middle_name

Itu dotenv untuk nodejs.

scottmotte
sumber
2
Atau cukup gunakan foreman run node xx.jsini akan secara otomatis membaca dalam file .env Anda juga.
Simon
1
Apakah saya akan menggunakan pendekatan ini untuk produksi juga?
Lama
1
@amar tidak, Anda mengaturnya dalam variabel env di server yang sebenarnya. Itu setiap kali Anda menyebarkan mereka ada di sana tetapi tidak dalam kode sumber.
sidonaldson
@Amar ya Anda bisa benar-benar, sebagai alternatif yang lebih portabel untuk mengatur variabel env di server. Poin pentingnya adalah untuk tidak menyertakan .envfile dalam kontrol versi atau proses penerapan Anda.
Josh Noe
31

Apakah kalian menggunakan npm untuk memulai skrip Anda (env dll)?

Jika Anda menggunakan .envfile, Anda dapat memasukkannya ke dalampackage.json dan menggunakan npm untuk sumber / memulainya.

Contoh:

{
  "name": "server",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node test.js",
    "start-dev": "source dev.env; node test.js",
    "start-prod": "source prod.env; node test.js"
  },
  "dependencies": {
    "mysql": "*"
  }
}

kemudian jalankan skrip npm:

$ npm start-dev

Ini dijelaskan di sini https://gist.github.com/ericelliott/4152984 Semua kredit untuk Eric Elliot

lxx
sumber
2
Bisakah Anda jelaskan apa itu "sumber"? Saya dapatkansource : not found
JohnnyBizzle
@JohnnyBizzle source(atau sederhananya, .) adalah perintah bawaan di shell Unix (Bash, dll.) Untuk membaca dan menjalankan perintah dari file yang diberikan, di shell saat ini . Artinya, perintah tidak dieksekusi dalam sub-shell. Efek dari hal itu dalam contoh ini adalah bahwa variabel lingkungan yang didefinisikan prod.envditambahkan ke shell saat ini dan karenanya, diteruskan ke setiap proses anak yang dihasilkan oleh shell ini. Anda sepertinya menggunakan Windows CMD. Lihat pertanyaan ini untuk lebih jelasnya.
Utku
Perlu dicatat - aplikasi 12 faktor merekomendasikan tidak membuat dev.envdan prod.env, tetapi memiliki satu .envfile per penyebaran.
Iiridayn
24

Anda mungkin juga melihat ke node-config yang memuat file konfigurasi tergantung pada variabel $ HOST dan $ NODE_ENV (sedikit seperti RoR): dokumentasi .

Ini bisa sangat berguna untuk pengaturan penyebaran yang berbeda ( development, testatau production).

orang Inggris
sumber
22

Cukup lakukan sederhana settings.jsdengan exports:

exports.my_password = 'value'

Kemudian, dalam skrip Anda, lakukan require:

var settings = require('./settings.js');

Semua pengaturan Anda sekarang akan tersedia melalui settingsvariabel:

settings.my_password // 'value'
Vanuan
sumber
@backdesk tentu saja Anda dapat mengatur sistem penyimpanan rahasia yang akan mengenkripsi rahasia dan membatasi akses menggunakan ip, beberapa token, dll. Tetapi pada akhirnya itu semua datang hanya dengan membaca beberapa file dari disk, apakah itu dienkripsi atau tidak.
Vanuan
@backdesk Tidak ada masalah dengan contohnya. Hanya itu: contoh untuk menjelaskan sesuatu yang konkret.
Emilio Grisolía
14

Saya akan melemparkan topi saya ke atas ring di sini karena tidak satu pun dari jawaban ini membahas semua komponen penting yang dibutuhkan sistem apa pun. Pertimbangan:

  • Konfigurasi publik (yang dapat dilihat oleh frontend) vs konfigurasi pribadi (guy mograbi mendapatkan hak ini). Dan memastikan ini disimpan terpisah.
  • Rahasia seperti kunci
  • Default vs penggantian khusus lingkungan
  • Bundel frontend

Inilah cara saya melakukan konfigurasi:

  • config.default.private.js - Dalam kontrol versi, ini adalah opsi konfigurasi default yang hanya dapat dilihat oleh backend Anda.
  • config.default.public.js- Dalam kontrol versi, ini adalah opsi konfigurasi default yang dapat dilihat oleh backend dan frontend
  • config.dev.private.js - Jika Anda memerlukan standar pribadi yang berbeda untuk dev.
  • config.dev.public.js - Jika Anda memerlukan default publik yang berbeda untuk dev.
  • config.private.js - Tidak dalam kontrol versi, ini adalah opsi khusus lingkungan yang menimpa config.default.private.js
  • config.public.js - Tidak dalam kontrol versi, ini adalah opsi khusus lingkungan yang menimpa config.default.public.js
  • keys/- Folder tempat setiap file menyimpan rahasia yang berbeda. Ini juga bukan di bawah kontrol versi (kunci tidak boleh berada di bawah kontrol versi).

Saya menggunakan file javascript biasa-lama untuk konfigurasi jadi saya memiliki kekuatan penuh dari langauge javascript (termasuk komentar dan kemampuan untuk melakukan hal-hal seperti memuat file konfigurasi default dalam file khusus lingkungan sehingga kemudian dapat diganti). Jika Anda ingin menggunakan variabel lingkungan, Anda dapat memuatnya di dalam file-file konfigurasi (tho saya sarankan agar tidak menggunakan env vars untuk alasan yang sama saya tidak merekomendasikan menggunakan file json - Anda tidak memiliki kekuatan bahasa pemrograman untuk membangun konfigurasi Anda).

Alasan setiap kunci dalam file terpisah adalah untuk penggunaan installer. Ini memungkinkan Anda untuk memiliki penginstal yang membuat kunci di mesin dan menyimpannya di folder kunci. Tanpa ini, installer Anda mungkin gagal ketika Anda memuat file konfigurasi Anda yang tidak dapat mengakses kunci Anda. Dengan cara ini Anda dapat melintasi direktori dan memuat file kunci apa pun yang ada di folder itu tanpa harus khawatir tentang apa yang ada dan apa yang tidak ada dalam versi kode Anda.

Karena Anda mungkin memiliki kunci yang dimuat dalam konfigurasi pribadi Anda, Anda pasti tidak ingin memuat konfigurasi pribadi Anda dalam kode frontend apa pun. Walaupun ini mungkin lebih ideal untuk memisahkan basis kode frontend Anda dari backend Anda, sering kali PITA merupakan penghalang yang cukup besar untuk mencegah orang melakukannya, dengan demikian konfigurasi privat vs publik. Tapi ada dua hal yang saya lakukan untuk mencegah konfigurasi pribadi dimuat di frontend:

  1. Saya memiliki unit test yang memastikan bundel frontend saya tidak mengandung salah satu kunci rahasia yang saya miliki di konfigurasi pribadi.
  2. Saya memiliki kode frontend saya di folder yang berbeda dari kode backend saya, dan saya memiliki dua file berbeda bernama "config.js" - satu untuk setiap ujung. Untuk backend, config.js memuat konfigurasi pribadi, untuk frontend, itu memuat konfigurasi publik. Maka Anda selalu hanya membutuhkan ('konfigurasi') dan jangan khawatir tentang dari mana asalnya.

Satu hal terakhir: konfigurasi Anda harus dimuat ke browser melalui file yang benar - benar terpisah dari kode frontend lainnya. Jika Anda bundel kode frontend Anda, konfigurasi publik harus dibangun sebagai bundel yang benar-benar terpisah. Jika tidak, konfigurasi Anda tidak benar-benar konfigurasi lagi - itu hanya bagian dari kode Anda. Config harus dapat berbeda pada mesin yang berbeda.

BT
sumber
13

Terpidana adalah pilihan lain yang menambahkan skema untuk validasi. Seperti nconf, ia mendukung pengaturan pemuatan dari kombinasi variabel lingkungan, argumen, file, dan objek json.

Contoh dari README:

var convict = require('convict');
var conf = convict({
  env: {
    doc: "The applicaton environment.",
    format: ["production", "development", "test"],
    default: "development",
    env: "NODE_ENV"
  },
  ip: {
    doc: "The IP address to bind.",
    format: "ipaddress",
    default: "127.0.0.1",
    env: "IP_ADDRESS",
  },
  port: {
    doc: "The port to bind.",
    format: "port",
    default: 0,
    env: "PORT"
  }
});

Artikel persiapan : Menjinakkan Konfigurasi dengan simpul-terpidana

hurrymaplelad
sumber
12

Anda dapat menggunakan Konfig untuk file konfigurasi khusus lingkungan. Ini memuat file konfigurasi json atau yaml secara otomatis, ia memiliki nilai default dan fitur konfigurasi dinamis.

Contoh dari Konfig repo:

File: config/app.json
----------------------------
{
    "default": {
        "port": 3000,
        "cache_assets": true,
        "secret_key": "7EHDWHD9W9UW9FBFB949394BWYFG8WE78F"
    },

    "development": {
        "cache_assets": false
    },

    "test": {
        "port": 3001
    },

    "staging": {
        "port": #{process.env.PORT},
        "secret_key": "3F8RRJR30UHERGUH8UERHGIUERHG3987GH8"
    },

    "production": {
        "port": #{process.env.PORT},
        "secret_key": "3F8RRJR30UHERGUH8UERHGIUERHG3987GH8"
    }
}

Dalam pengembangan:

> config.app.port
3000

Dalam produksi, anggap kita memulai aplikasi dengan $ NODE_ENV=production PORT=4567 node app.js

> config.app.port
4567

Rincian lebih lanjut: https://github.com/vngrs/konfig

Ali Davut
sumber
9

Saya akan membuat folder sebagai config penamaan file config.jsdan kemudian saya akan menggunakan file ini dimanapun diperlukan seperti di bawah ini

Contoh config.js

module.exports = {
    proxyURL: 'http://url:port',
    TWITTER: {
        consumerkey: 'yourconsumerkey',
        consumerSecrete: 'yourconsumersecrete'
    },
    GOOGLE: {
        consumerkey: 'yourconsumerkey',
        consumerSecrete: 'yourconsumersecrete'
    },
    FACEBOOK: {
        consumerkey: 'yourconsumerkey',
        consumerSecrete: 'yourconsumersecrete'
    }
}

Lalu jika saya ingin menggunakan file konfigurasi ini di suatu tempat

Pertama-tama saya akan mengimpor seperti di bawah ini

var config = require('./config');

dan saya dapat mengakses nilai-nilai seperti di bawah ini

const oauth = OAuth({
    consumer: {
        key: config.TWITTER.consumerkey,
        secret: config.TWITTER.consumerSecrete
    },
    signature_method: 'HMAC-SHA1',
    hash_function(base_string, key) {
        return crypto.createHmac('sha1', key).update(base_string).digest('base64');
    }
});
Ron
sumber
6

Cukup gunakan npmmodul config(lebih dari 300000 unduhan)

https://www.npmjs.com/package/config

Node-config mengatur konfigurasi hierarkis untuk penerapan aplikasi Anda.

Ini memungkinkan Anda menentukan seperangkat parameter default, dan memperluasnya untuk lingkungan penyebaran yang berbeda (pengembangan, qa, pementasan, produksi, dll.).

$ npm install config
$ mkdir config
$ vi config/default.json


{
      // Customer module configs
      "Customer": {
        "dbConfig": {
          "host": "localhost",
          "port": 5984,
          "dbName": "customers"
        },
        "credit": {
          "initialLimit": 100,
          // Set low for development
          "initialDays": 1
        }
      }
}



$ vi config/production.json

{
  "Customer": {
    "dbConfig": {
      "host": "prod-db-server"
    },
    "credit": {
      "initialDays": 30
    }
  }
}



$ vi index.js

var config = require('config');
//...
var dbConfig = config.get('Customer.dbConfig');
db.connect(dbConfig, ...);

if (config.has('optionalFeature.detail')) {
  var detail = config.get('optionalFeature.detail');
  //...
}


$ export NODE_ENV=production
$ node index.js
aflex dykyі
sumber
4

Lebih baik memisahkan konfigurasi 'pengembangan' dan 'produksi' .

Saya menggunakan cara berikut: Ini adalah file config / index.js saya :

const config = {
    dev : {
        ip_address : '0.0.0.0',
        port : 8080,
        mongo :{
            url : "mongodb://localhost:27017/story_box_dev",
            options : ""
        }
    },
    prod : {
        ip_address : '0.0.0.0',
        port : 3000,
        mongo :{
            url : "mongodb://localhost:27017/story_box_prod",
            options : ""
        }
    }
} 

Untuk memerlukan konfigurasi gunakan sebagai berikut:

const config = require('../config')[process.env.NODE_ENV];

Daripada Anda dapat menggunakan objek konfigurasi Anda:

const ip_address = config.ip_address;
const port = config.port;
Aram Manukyan
sumber
Anda juga dapat pengguna module.exports = config;di akhir config/index.jsfile
mapmalith
3

Saya agak terlambat dalam permainan, tetapi saya tidak dapat menemukan apa yang saya butuhkan di sini - atau di tempat lain - jadi saya menulis sesuatu sendiri.

Persyaratan saya untuk mekanisme konfigurasi adalah sebagai berikut:

  1. Mendukung front-end. Apa gunanya jika front-end tidak dapat menggunakan konfigurasi?
  2. Dukungan settings-overrides.js- yang terlihat sama tetapi memungkinkan penggantian konfigurasi settings.js. Idenya di sini adalah untuk memodifikasi konfigurasi dengan mudah tanpa mengubah kode. Saya menemukan itu berguna untuk sauna.

Meskipun saya kurang peduli tentang lingkungan pendukung - kehendak menjelaskan cara menambahkannya dengan mudah ke solusi saya

var publicConfiguration = {
    "title" : "Hello World"
    "demoAuthToken" : undefined, 
    "demoUserId" : undefined, 
    "errorEmail" : null // if null we will not send emails on errors. 

};

var privateConfiguration = {
    "port":9040,
    "adminAuthToken":undefined,
    "adminUserId":undefined
}

var meConf = null;
try{
    meConf = require("../conf/dev/meConf");
}catch( e ) { console.log("meConf does not exist. ignoring.. ")}




var publicConfigurationInitialized = false;
var privateConfigurationInitialized = false;

function getPublicConfiguration(){
    if (!publicConfigurationInitialized) {
        publicConfigurationInitialized = true;
        if (meConf != null) {
            for (var i in publicConfiguration) {
                if (meConf.hasOwnProperty(i)) {
                    publicConfiguration[i] = meConf[i];
                }
            }
        }
    }
    return publicConfiguration;
}


function getPrivateConfiguration(){
    if ( !privateConfigurationInitialized ) {
        privateConfigurationInitialized = true;

        var pubConf = getPublicConfiguration();

        if ( pubConf != null ){
            for ( var j in pubConf ){
                privateConfiguration[j] = pubConf[j];
            }
        }
        if ( meConf != null ){
              for ( var i in meConf ){
                  privateConfiguration[i] = meConf[i];
              }
        }
    }
    return privateConfiguration;

}


exports.sendPublicConfiguration = function( req, res ){
    var name = req.param("name") || "conf";

    res.send( "window." + name + " = " + JSON.stringify(getPublicConfiguration()) + ";");
};


var prConf = getPrivateConfiguration();
if ( prConf != null ){
    for ( var i in prConf ){
        if ( prConf[i] === undefined ){

            throw new Error("undefined configuration [" + i + "]");
        }
        exports[i] = prConf[i];
    }
}


return exports;

Penjelasan

  • undefined berarti properti ini diperlukan
  • null berarti itu opsional
  • meConf- Saat ini kode tersebut ditargetkan ke file di bawah app. meConfadalah file utama yang ditargetkan untuk conf/dev- yang diabaikan oleh vcs saya.
  • publicConfiguration - Akan terlihat dari front-end dan back-end.
  • privateConfiguration - Akan terlihat dari back-end saja.
  • sendPublicConfiguration- rute yang akan mengekspos konfigurasi publik dan menetapkannya ke variabel global. Sebagai contoh, kode di bawah ini akan memperlihatkan konfigurasi publik sebagai variabel global myConf di front-end. Secara default akan menggunakan nama variabel globalconf .

    app.get ("/ backend / conf", memerlukan ("conf"). sendPublicConfiguration);

Logika penimpaan

  • privateConfiguration digabung dengan publicConfiguration dan kemudian meConf.
  • publicConfiguration memeriksa setiap kunci jika ada override, dan menggunakan override itu. Dengan cara ini kami tidak mengekspos sesuatu yang bersifat pribadi.

Menambahkan dukungan lingkungan

Meskipun saya tidak menemukan "dukungan lingkungan" berguna, mungkin seseorang akan melakukannya.

Untuk menambahkan dukungan lingkungan Anda perlu mengubah meConf membutuhkan pernyataan untuk sesuatu seperti ini (pseudocode)

if (environment == "production") {meConf = require ("../ conf / dev / meConf"). produksi; }

if (environment == "development") {meConf = membutuhkan ("../ conf / dev / meConf"). development; }

Demikian pula Anda dapat memiliki file per lingkungan

 meConf.development.js
 meConf.production.js

dan impor yang benar. Logika lainnya tetap sama.

orang mograbi
sumber
tidak terlalu jelas yang undefinedbenar - benar berarti 'wajib' dan nullberarti 'opsional'. jadi bin kuning untuk plastik dan biru untuk kertas bekas? baik, tetapi harus membaca manual sebelum membuang sampah itu.
mengalir
Anda tidak harus menggunakan konvensi ini. Saya merasa ini berguna dan saya menginstruksikan tim saya untuk menggunakannya, tetapi Anda jelas dapat menghapus fitur ini.
guy mograbi
3

contoh alt yang baru saja saya gunakan karena saya ingin lebih banyak fleksibilitas daripada file .json yang khas tetapi tidak ingin disarikan ke perpustakaan yang memerlukan ketergantungan adalah sesuatu seperti ini. Pada dasarnya, mengekspor fungsi yang dipanggil segera yang mengembalikan objek dengan nilai yang ingin saya atur. Memberikan banyak fleksibilitas.

     module.exports = function(){
       switch(node_env){
         case 'dev':
           return
           { var1 = 'development'};
         }
    }();

Ada penjelasan yang jauh lebih baik dengan contoh lengkap di sini. Menggunakan File Config di Node.js

captainavi
sumber
3

Saya tahu ini adalah posting yang sangat lama. Tetapi saya ingin membagikan modul saya untuk mengonfigurasi variabel lingkungan, saya pikir ini adalah solusi yang sangat fleksibel. Berikut ini adalah modul json-configurator

var configJson = {
  'baseUrl': 'http://test.com',
  '$prod_baseUrl': 'https://prod.com',
  'endpoints': {
    'users': '<%= baseUrl %>/users',
    'accounts': '<%= baseUrl %>/accounts'
    },
  foo: 'bar',
  foobar: 'foobar',
  $prod_foo: 'foo in prod',
  $test_foo: 'foo in test',
  deep:{
    veryDeep: {
      publicKey: 'abc',
      secret: 'secret',
      $prod_secret: 'super secret'
    }
  }
};

var config = require('json-configurator')(configJson, 'prod');

console.log(config.deep.veryDeep.secret) 
// super secret 

console.log(config.endpoints.users)
// https://prod.com/users 

Kemudian Anda dapat menggunakan process.env.NODE_ENVuntuk mendapatkan semua variabel untuk lingkungan Anda.

Kristen
sumber
2

Selain modul nconf yang disebutkan dalam jawaban ini , dan node-config yang disebutkan dalam jawaban ini , ada juga node-iniparser dan IniReader , yang tampaknya menjadi parser file konfigurasi .ini yang lebih sederhana.

Wingman4l7
sumber
tidak ada cara untuk kembali ke file win-ini ... yang iniparserdengan bangga menekankan fakta bahwa mereka tahu cara mem-parsing bagian dalam konfigurasi ... pada 2013 ... jika Anda perlu bersarang lebih dalam, menurut Anda [foo/bar]? [foo\bar]? bar.baz=42? bar/baz=42? bar\baz=42? bar:baz=42? bagaimana Anda tahu 42nomor? itu bisa berupa teks semua-digit! —buang XML, lempar YAML, lempar WIN.INI, rangkul JSON, kekhawatiran hilang.
mengalir
1

Anda dapat menggunakan pconf: https://www.npmjs.com/package/pconf

Contoh:

var Config = require("pconf");
var testConfig = new Config("testConfig");
testConfig.onload = function(){

  testConfig.setValue("test", 1);
  testConfig.getValue("test");
  //testConfig.saveConfig(); Not needed

}
Per Henrik Jakobsson
sumber
1

Berikut ini adalah pendekatan rapi yang terinspirasi oleh artikel ini . Ini tidak memerlukan paket tambahan kecuali di mana-mana paket lodash . Selain itu, ini memungkinkan Anda mengelola standar bersarang dengan timpa khusus lingkungan.

Pertama, buat folder config di path root paket yang terlihat seperti ini

package
  |_config
      |_ index.js
      |_ defaults.json
      |_ development.json
      |_ test.json
      |_ production.json

di sini adalah file index.js

const _ = require("lodash");
const defaults = require("./defaults.json");
const envConf = require("./" + (process.env.NODE_ENV || "development") + ".json" );
module.exports = _.defaultsDeep(envConf, defaults);

Sekarang mari kita asumsikan kita memiliki defaults.json seperti itu

{
  "confKey1": "value1",
  "confKey2": {
    "confKey3": "value3",
    "confKey4": "value4"
  }
}

dan development.json seperti itu

{
  "confKey2": {
    "confKey3": "value10",
  }
}

jika Anda lakukan di config = require('./config')sini adalah apa yang akan Anda dapatkan

{
  "confKey1": "value1",
  "confKey2": {
    "confKey3": "value10",
    "confKey4": "value4"
  }
}

Perhatikan bahwa Anda mendapatkan semua nilai default kecuali yang ditentukan dalam file khusus lingkungan. Jadi, Anda dapat mengelola hierarki konfigurasi. Menggunakan defaultsDeepmemastikan bahwa Anda bahkan dapat memiliki standar bersarang.

Rahul
sumber
0

Saya mencoba beberapa solusi yang disarankan di sini, tetapi tidak puas dengan mereka, jadi saya membuat modul saya sendiri. Itu disebutmikro-config dan perbedaan utamanya adalah ia menghormati konvensi atas konfigurasi, jadi Anda hanya dapat memerlukan modul dan mulai menggunakannya.

Anda menyimpan konfigurasi Anda dalam file js, atau json biasa dari /configfolder. Pertama memuat default.jsfile, lalu semua file lain dari /configdirektori, lalu memuat konfigurasi khusus lingkungan berdasarkan $NODE_ENVvariabel.

Ini juga memungkinkan untuk mengganti konfigurasi ini untuk pengembangan lokal dengan local.jsatau khusus lingkungan /config/env/$NODE_ENV.local.js.

Anda dapat melihatnya di sini:

https://www.npmjs.com/package/mikro-config

https://github.com/B4nan/mikro-config

Martin Adámek
sumber
0

Untuk waktu yang lama, saya terbiasa menggunakan pendekatan yang disebutkan dalam solusi di sini. Namun ada kekhawatiran, tentang keamanan rahasia dalam teks yang jelas. Anda dapat menggunakan paket lain di atas configsehingga bit keamanan dijaga.

Lihat ini: https://www.attosol.com/secure-application-secrets-using-masterkey-in-azure-key-vault/

Rahul Soni
sumber
Mengapa saya harus berlangganan Azure untuk membayar layanan ini? Mengapa tidak menggunakan ansible-vault? Hal lain: Saya pikir tidak ada yang akan memposting file konfigurasi dengan kredensial teks yang jelas pada repositori sumber. Baik gunakan variabel lingkungan atau letakkan data rahasia Anda pada file dengan izin hanya baca.
Yasser Sinjab
Jika Anda dapat membacanya dari beberapa lokasi pihak ke-3 dan men-decode-nya dan meminta layanan Anda menggunakan data rahasia tersebut, peretas mungkin saja melakukan hal yang sama jika mereka mendapatkan akses ke komputer Anda. Ini lebih banyak pekerjaan (membutuhkan waktu lebih lama) tetapi pada akhirnya itu tidak melindungi Anda. Jika server Anda ditembus, bayangkan apa pun yang Anda miliki sekarang publik.
Alexis Wilke