Jak przechowywać pliki ustawień / konfiguracji wdrażania Node.js?


640

Pracowałem nad kilkoma aplikacjami Node i szukałem dobrego wzorca przechowywania ustawień związanych z wdrażaniem. W świecie Django (skąd pochodzę) powszechną praktyką byłoby posiadanie settings.pypliku zawierającego ustawienia standardowe (strefa czasowa itp.), A następnie local_settings.pyustawienia specyficzne dla wdrożenia, tj. z jaką bazą danych rozmawiać, z jakim gniazdem memcache, adresem e-mail dla administratorów i tak dalej.

Szukałem podobnych wzorów dla Węzła. Po prostu plik konfiguracyjny byłby fajny, więc nie trzeba go zacinać z całą resztą app.js, ale uważam, że ważne jest, aby mieć sposób na konfigurację specyficzną dla serwera w pliku, który nie jest pod kontrolą źródła. Ta sama aplikacja mogłaby zostać wdrożona na różnych serwerach przy bardzo różnych ustawieniach i konieczności radzenia sobie z konfliktami scalania i wszystkim, co nie jest moim pomysłem na zabawę.

Czy jest w tym jakiś jakiś szkielet / narzędzie, czy może wszyscy sami coś razem zhakują?


Bardzo podoba mi się sposób, konfiguracja odbywa się w mean.js . w zasadzie przechowują odpowiednią konfigurację aplikacji w osobnym module, w oparciu o różne ustawienia dla środowiska aplikacji (do produkcji, rozwoju, testowania) i przekazując określone szczegóły poprzez zmienne środowiskowe aplikacji, takie jak sekrety itp.
Hinrich

Odpowiedzi:


765

Używam a package.jsondla moich pakietów i config.jsdla mojej konfiguracji, która wygląda następująco:

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;

Ładuję konfigurację z mojego projektu:

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

i wtedy mogę uzyskać dostęp do moich rzeczy z config.db_host, config.db_portitd ... To pozwala mi użyć sztywno parametry lub parametrów zapisanych w zmiennych środowiskowych, jeśli nie chcesz zapisywać hasła w kontroli źródła.

Generuję również package.jsoni wstawiam sekcję zależności:

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

Kiedy klonuję projekt na moją maszynę lokalną, biegam, npm installaby zainstalować pakiety. Więcej informacji na ten temat tutaj .

Projekt jest przechowywany w GitHub, z pilotami dodanymi do mojego serwera produkcyjnego.


32
co się stanie, gdy masz różne ustawienia konfiguracji dla programisty vs. producenta?
chovy

4
Nie mam, ale jest jeden sposób, aby to zrobić ... dla każdej env ustaw nazwę env w zmiennej ENV. Następnie w tym pliku jest to po prostu javascript .. użyj instrukcji case lub if, aby selektywnie załadować odpowiednie zmienne. Możesz nawet utworzyć osobny podtekst konfiguracji dla każdej env, a w instrukcji if ponownie załaduj podtekst tutaj do zmiennej podkonfiguracyjnej i wyeksportuj tę podkonfigurację var do głównej konfiguracji. Próbuję tylko powiedzieć, że jest to po prostu js, więc możesz być kreatywny
noli

4
jaki proces.env? gdzie to się znajduje? I jak to ustawić?
zły kiwi

12
Myślałem „wow .. patrzyłem na node.js od kilku godzin, a moja aplikacja już działa… btw, może podzielę się tym losowym fragmentem kodu, który wymyśliłem”
noli

3
Czy nadal nie możesz używać zmiennych środowiskowych do przechowywania tych haseł? Czy nie po to jest ten wiersz: config.twitter.password = process.env.TWITTER_PASSWORD || 'hasło';
DMart

244

Możesz wymagać plików JSON od Node v0.5.x ( odwołując się do tej odpowiedzi )

config.json:

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

app.js:

var config = require('./config.json');
log_in(config.username, config.password);

40
Nie jestem pod wrażeniem tej funkcji. Możesz wymagać („./ config.js”), a otrzymasz możliwość dodawania komentarzy do plików konfiguracyjnych, które uważam za bardzo ważne, oraz innych dzwonków i gwizdków. Jeśli config jest tylko właściwościami, a żaden kod nie traci nic, wymagając (config.js) z tobą JSON z prefiksem
exports.config

3
@teknopaul masz rację, ale toczyła się duża dyskusja na temat „poprawności” / użyteczności używania głupiego vs. inteligentnego systemu szablonów, który powiedział mi: (1) zazwyczaj chcesz deklaratywny / głupi język dla szablonów / opcji (2) złym pomysłem jest zrekonstruowanie „prawie PL”, aby po prostu wykonać szablony (lub konfigurację) - lepiej użyć ponownie istniejącej prawdziwej PL ze znanymi zachowaniami. w jak dotąd +1 za recykling JS w celu wykonania ustawień użytkownika; -1 za brak podejścia deklaratywnego. widzieliśmy kilka dość złożonych rzeczy konfiguracyjnych wykonanych w sposób deklaratywny; moje wnętrzności mówią mi, że to jest właściwa droga.
przepływ

1
Brak inteligencji na obiektach z plików json w VScode (koniec 2017 r.). W pełni działający intellisense dla obiektów z module.exports.
Romain Vincent

199

Znacznie później znalazłem całkiem niezły moduł Node.js do zarządzania konfiguracją: nconf .

Prosty przykład:

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

Obsługuje również przechowywanie ustawień w Redis , pisanie plików konfiguracyjnych i ma dość solidny interfejs API, a także jest wspierany przez jeden z bardziej szanowanych sklepów Node.js, Nodejitsu , w ramach inicjatywy frameworku Flatiron , więc powinno być dość przyszłościowe.

Sprawdź nconf na Github .


2
Może głupie pytanie, ale nie widziałem jasnego wyjaśnienia: gdzie ustawić zmienne środowiskowe węzła? Już używam nconf, ale nie jest jasne, gdzie ustawiłbym zmienne środowiskowe. Czy to jest w Nginx / Apache? Czy to kolejny plik konfiguracyjny?
Cywil

91
Nie sądzę, aby używać pliku .json jako konfiguracji jest dobrym pomysłem, ponieważ komentarze nie są dozwolone.
Frank Xu,

11
To wygląda świetnie. Myślę, że zaskoczysz wiele Unixheadów, jeśli plik konfiguracyjny zastąpi opcje wiersza polecenia i zmienne środowiskowe. Jesteśmy przyzwyczajeni do następującej kolejności rosnących priorytetów: pliki konfiguracyjne, zmienne środowiskowe, opcje wiersza polecenia.
sheldonh

2
@ sheldonh Poczekaj, aż dowiesz się, że opcje logiczne są zawsze ustawione na argv, dlatego łamanie pierwszeństwa ...: /
Daniel C. Sobral

@ DanielC.Sobral To prawdziwy wstyd. Aha, i LTNS! :-)
sheldonh

94

Moje rozwiązanie jest dość proste:

Załaduj konfigurację środowiska do ./config/index.js

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

module.exports = cfg;

Zdefiniuj niektóre wartości domyślne w ./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';

Zastąp wartości domyślne w ./config/config.test.js

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

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

module.exports = config;

Używając go w ./models/user.js:

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

Uruchamianie aplikacji w środowisku testowym:

NODE_ENV=test node ./app.js

2
Wolę tą. Jak wspomnieli inni, JSON nie jest preferowaną strukturą pamięci, a nakładanie warstw na globale jest proste i skuteczne
Sebastian J.,

Jedynym powodem, dla którego wolę to od nconf, jest to, że zezwala na format .js dla plików konfiguracyjnych (dev, test i prod). co pozwala nam udokumentować każdą opcję konfiguracji, która w innym przypadku nie byłaby możliwa w formacie JSON.
Kunal Kapadia

BTW, NODE_ENVdomyślnie jest to „programowanie”. Zamiast tego powinieneś sprawdzić „produkcję”.
Kevin Suttle

5
Nie sprawdzam rozwoju. Domyślam się tego. Nie jestem pewien, dlaczego miałbym kiedykolwiek zacząć od produkcji.
chovy

39

Możesz także spojrzeć na dotenv, który jest zgodny z założeniami aplikacji dwunastoczynnikowej .

Kiedyś korzystałem z node-config, ale z tego powodu stworzyłem dotenv. Został całkowicie zainspirowany biblioteką dotenv Ruby.

Użycie jest dość łatwe:

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

Następnie wystarczy utworzyć plik .env i umieścić tam swoje ustawienia w następujący sposób:

S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE
OTHER_SECRET_STUFF=my_cats_middle_name

To jest dotenv dla nodejs.


2
Lub po prostu użyj foreman run node xx.jstego automatycznie odczyta również w pliku .env.
Simon

1
czy zastosowałbym to podejście również do produkcji?
Lamour,

1
@lamar nie, ustawiasz je w zmiennych env na rzeczywistym serwerze. Tak było przy każdym wdrożeniu, ale są tam, ale nie w kodzie źródłowym.
sidonaldson,

@Lamar tak, faktycznie możesz, jako bardziej przenośna alternatywa dla ustawiania zmiennych env na serwerze. Ważne jest, aby nie włączać .envpliku do procesu kontroli wersji lub procesu wdrażania.
Josh Noe,

31

Czy używacie npm do uruchamiania skryptów (env itp.)?

Jeśli używasz .envplików, możesz dołączyć je do swojego package.json i użyć npm do ich źródła / uruchomienia.

Przykład:

{
  "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": "*"
  }
}

następnie uruchom skrypty npm:

$ npm start-dev

Jest to opisane tutaj https://gist.github.com/ericelliott/4152984 Wszystkie podziękowania dla Erica Elliota


2
Czy możesz wyjaśnić, czym jest „źródło”? Rozumiemsource : not found
JohnnyBizzle

@JohnnyBizzle source(lub po prostu .) to wbudowane polecenie w powłokach uniksowych (Bash itp.) Do odczytu i wykonywania poleceń z podanego pliku w bieżącej powłoce . Oznacza to, że polecenia nie są wykonywane w podpowłoce. Efektem tego w tym przykładzie jest to, że zmienne środowiskowe zdefiniowane w prod.envsą dodawane do bieżącej powłoki, a zatem przekazywane do dowolnego procesu potomnego odradzanego przez tę powłokę. Wygląda na to, że używasz Windows CMD. Zobacz to pytanie, aby uzyskać więcej informacji.
Utku,

Warto zauważyć - aplikacja 12-czynnikowa zaleca nie tworzenie dev.envi prod.envposiadanie jednego .envpliku na wdrożenie.
Iiridayn

24

Możesz także zajrzeć do config-node, który ładuje plik konfiguracyjny w zależności od $ HOST i zmiennej $ NODE_ENV (trochę jak RoR): dokumentacja .

To może być bardzo przydatne dla różnych ustawień programowych ( development, testlub production).


22

Po prostu zrób proste settings.jsz exports:

exports.my_password = 'value'

Następnie w skrypcie wykonaj require:

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

Wszystkie twoje ustawienia będą teraz dostępne poprzez settingszmienną:

settings.my_password // 'value'

@ backdesk oczywiście możesz skonfigurować tajny system przechowywania, który szyfruje tajemnice i ogranicza dostęp za pomocą adresu IP, niektórych tokenów itp. Ale pod koniec dnia wszystko sprowadza się do odczytu niektórych plików z dysku, czy to zaszyfrowanych, czy nie.
Vanuan

@backdesk Nie ma problemu z przykładem. Czy to po prostu: przykład na wyjaśnienie czegoś konkretnego.
Emilio Grisolía

14

Mam zamiar rzucić tu kapelusz na ring, ponieważ żadna z tych odpowiedzi nie dotyczy wszystkich krytycznych komponentów, których właściwie potrzebuje każdy system. Uwagi:

  • Konfiguracja publiczna (którą widać w interfejsie użytkownika) a konfiguracja prywatna (facet mograbi dobrze to zrozumiał). I upewnienie się, że są one oddzielone.
  • Tajemnice jak klucze
  • Ustawienia domyślne a przesłonięcia specyficzne dla środowiska
  • Pakiety Frontend

Oto jak wykonuję moją konfigurację:

  • config.default.private.js - W kontroli wersji są to domyślne opcje konfiguracji, które mogą być widoczne tylko przez backend.
  • config.default.public.js- W kontroli wersji są to domyślne opcje konfiguracji, które mogą być widoczne przez backend i frontend
  • config.dev.private.js - Jeśli potrzebujesz różnych ustawień domyślnych dla dev.
  • config.dev.public.js - Jeśli potrzebujesz różnych publicznych ustawień domyślnych dla programisty.
  • config.private.js - Brak kontroli wersji, są to opcje specyficzne dla środowiska, które zastępują config.default.private.js
  • config.public.js - Brak kontroli wersji, są to opcje specyficzne dla środowiska, które zastępują config.default.public.js
  • keys/- Folder, w którym każdy plik przechowuje inny sekret. To również nie jest pod kontrolą wersji (klucze nigdy nie powinny być pod kontrolą wersji).

Używam zwykłych plików javascript do konfiguracji, więc mam pełną moc językowego języka javascript (w tym komentarze i możliwość robienia rzeczy takich jak ładowanie domyślnego pliku konfiguracyjnego do pliku specyficznego dla środowiska, aby można je było następnie zastąpić). Jeśli chcesz użyć zmiennych środowiskowych, możesz załadować je do tych plików konfiguracyjnych (odradzam używanie env vars z tego samego powodu, dla którego nie polecam używania plików json - nie masz mocy języka programowania do zbudowania Twoja konfiguracja).

Powodem, dla którego każdy klucz znajduje się w osobnym pliku, jest użycie przez instalatora. To pozwala mieć instalatora, który tworzy klucze na komputerze i przechowuje je w folderze kluczy. Bez tego instalator może się nie powieść po załadowaniu pliku konfiguracyjnego, który nie może uzyskać dostępu do kluczy. W ten sposób możesz przeglądać katalog i ładować dowolne pliki kluczy znajdujące się w tym folderze bez martwienia się o to, co istnieje, a czego nie ma w żadnej wersji kodu.

Ponieważ prawdopodobnie masz klucze załadowane w konfiguracji prywatnej, zdecydowanie nie chcesz ładować konfiguracji prywatnej w żadnym kodzie interfejsu użytkownika. Chociaż prawdopodobnie jest to bardziej idealne rozwiązanie, aby całkowicie oddzielić bazę kodu frontendu od backendu, wiele razy PITA jest wystarczająco dużą barierą, aby uniemożliwić ludziom to zrobić, a więc konfigurację prywatną lub publiczną. Ale robię dwie rzeczy, aby zapobiec ładowaniu prywatnej konfiguracji w interfejsie:

  1. Mam test jednostkowy, który upewnia się, że moje pakiety frontendowe nie zawierają jednego z tajnych kluczy, które mam w konfiguracji prywatnej.
  2. Mam kod frontendowy w innym folderze niż kod backendowy i mam dwa różne pliki o nazwie „config.js” - po jednym dla każdego końca. Dla backendu config.js ładuje konfigurację prywatną, dla frontendu ładuje konfigurację publiczną. Następnie zawsze potrzebujesz („config”) i nie martw się o to, skąd pochodzi.

I ostatnia rzecz: twoja konfiguracja powinna zostać załadowana do przeglądarki za pomocą zupełnie osobnego pliku niż jakikolwiek inny kod frontendowy. Jeśli dołączysz kod frontendu, konfiguracja publiczna powinna zostać zbudowana jako całkowicie oddzielny pakiet. W przeciwnym razie twoja konfiguracja nie jest już tak naprawdę konfiguracją - to tylko część kodu. Konfiguracja musi być inna na różnych komputerach.


13

Skazanie to kolejna opcja, która dodaje schemat sprawdzania poprawności. Podobnie jak nconf, obsługuje ładowanie ustawień z dowolnej kombinacji zmiennych środowiskowych, argumentów, plików i obiektów json.

Przykład z pliku 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"
  }
});

Artykuł wprowadzający: Oswajanie konfiguracji za pomocą węzła skazującego


12

Możesz użyć Konfig do plików konfiguracyjnych specyficznych dla środowiska. Ładuje automatycznie pliki konfiguracyjne json lub yaml, ma wartość domyślną i funkcje konfiguracji dynamicznej.

Przykład z repozytorium Konfig:

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

W fazie rozwoju:

> config.app.port
3000

Załóżmy, że w produkcji zaczynamy od aplikacji $ NODE_ENV=production PORT=4567 node app.js

> config.app.port
4567

Więcej informacji: https://github.com/vngrs/konfig


9

Utworzę folder jako nazwę pliku konfiguracji, config.jsa później będę go używać wszędzie tam, gdzie jest to wymagane, jak poniżej

Przykład config.js

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

Więc jeśli chcę gdzieś użyć tego pliku konfiguracyjnego

Najpierw zaimportuję jak poniżej

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

i mogę uzyskać dostęp do wartości jak poniżej

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

5

Wystarczy użyć npmmodułu config(ponad 300 000 pobrań)

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

Node-config organizuje hierarchiczne konfiguracje dla wdrożeń aplikacji.

Pozwala zdefiniować zestaw parametrów domyślnych i rozszerzyć je dla różnych środowisk wdrażania (programowanie, qa, przemieszczanie, produkcja itp.).

$ 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

4

Lepiej oddzielić konfiguracje „programistyczne” i „produkcyjne” .

Używam następującego sposobu: Oto mój plik config / index.js :

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

Aby wymagać konfiguracji użyj:

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

Następnie możesz użyć obiektu konfiguracji:

const ip_address = config.ip_address;
const port = config.port;

możesz również użytkownik module.exports = config;na końcu config/index.jspliku
mapmalith

3

Jestem trochę spóźniony w grze, ale nie mogłem znaleźć tego, czego potrzebowałem tutaj - ani nigdzie indziej - więc sam coś napisałem.

Moje wymagania dotyczące mechanizmu konfiguracji są następujące:

  1. Obsługuje front-end. Po co front-end nie może korzystać z konfiguracji?
  2. Obsługa settings-overrides.js- która wygląda tak samo, ale umożliwia zastąpienie konfiguracji w settings.js. Chodzi tutaj o łatwą modyfikację konfiguracji bez zmiany kodu. Uważam, że jest to przydatne do saas.

Mimo że mniej zależy mi na wspieraniu środowisk - wyjaśnię, jak łatwo to dodać do mojego rozwiązania

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;

Wyjaśnienie

  • undefined oznacza, że ​​ta właściwość jest wymagana
  • null oznacza, że ​​jest opcjonalny
  • meConf- obecnie kod jest kierowany do pliku poniżej app. meConfjest nadpisuje pliki, do których jest skierowane conf/dev- co jest ignorowane przez moje vcs.
  • publicConfiguration - będą widoczne z przodu i tyłu.
  • privateConfiguration - będzie widoczny tylko z zaplecza.
  • sendPublicConfiguration- trasa, która ujawni konfigurację publiczną i przypisze ją do zmiennej globalnej. Na przykład poniższy kod ujawni konfigurację publiczną jako zmienną globalną myConf w interfejsie. Domyślnie użyje globalnej nazwy zmiennejconf .

    app.get („/ backend / conf”, wymagają („conf”). sendPublicConfiguration);

Logika przesłonięć

  • privateConfiguration jest łączony z publicConfiguration, a następnie meConf.
  • publicConfiguration sprawdza każdy klucz, jeśli ma zastąpienie, i używa tego zastąpienia. W ten sposób nie ujawniamy niczego prywatnego.

Dodanie obsługi środowiska

Chociaż nie uważam, że „wsparcie środowiska” jest przydatne, może ktoś to zrobi.

Aby dodać obsługę środowiska, musisz zmienić instrukcję meConf na coś takiego (pseudokod)

if (środowisko == „produkcja”) {meConf = wymagają („../ conf / dev / meConf”). produkcja; }

if (środowisko == „rozwój”) {meConf = wymagany („../ conf / dev / meConf”). development; }

Podobnie możesz mieć plik na środowisko

 meConf.development.js
 meConf.production.js

i zaimportuj właściwy. Reszta logiki pozostaje taka sama.


niezbyt oczywiste, że undefinedtak naprawdę oznacza „wymagane” i null„opcjonalne”. więc żółty pojemnik jest na plastik, a niebieski na złom? dobrze, ale musiałem przeczytać instrukcję przed podrzuceniem tego miotu.
przepływ

Nie musisz używać tej konwencji. Uważam to za przydatne i polecam zespołowi, aby z niego korzystał, ale oczywiście możesz usunąć tę funkcję.
guy mograbi

3

alternatywny przykład, którego właśnie użyłem, ponieważ chciałem większej elastyczności niż typowy plik .json, ale nie chciałem abstrakcji go do biblioteki wymagającej zależności, jest coś takiego. Zasadniczo eksport funkcji wywoływanej natychmiast, która zwróciła obiekt o wartościach, które chciałem ustawić. Daje dużą elastyczność.

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

Istnieje o wiele lepsze wytłumaczenie z pełnym przykładem tutaj. Używanie plików konfiguracji w Node.js


3

Wiem, że to naprawdę stary post. Ale chcę udostępnić mój moduł do konfigurowania zmiennych środowiskowych, myślę, że jest to bardzo elastyczne rozwiązanie. Oto moduł json-konfigurator

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 

Następnie możesz użyć, process.env.NODE_ENVaby uzyskać wszystkie zmienne dla swojego środowiska.


2

Oprócz modułu nconf wspomnianego w tej odpowiedzi i węzła config wspomnianego w tej odpowiedzi , istnieją również węzły iniparser i IniReader , które wydają się być prostszymi parserami plików konfiguracyjnych .ini.


nie ma możliwości powrotu do plików win-ini ... co z iniparserdumą podkreśla fakt, że wiedzą, jak parsować sekcje w konfiguracji ... w 2013 ... jeśli potrzebujesz głębszego zagnieżdżenia, prawda [foo/bar]? [foo\bar]? bar.baz=42? bar/baz=42? bar\baz=42? bar:baz=42? skąd wiesz, że 42jest liczbą? może to być tekst składający się z samych cyfr! - podrzuć XML, podrzuć YAML, podrzuć WIN.INI, obejrzyj JSON, zmartwienia zniknęły.
przepływ



1

Oto schludne podejście inspirowane tym artykułem . Nie wymaga żadnych dodatkowych pakietów oprócz wszechobecnego pakietu Lodash . Ponadto pozwala zarządzać zagnieżdżonymi ustawieniami domyślnymi za pomocą nadpisywania specyficznego dla środowiska.

Najpierw utwórz folder konfiguracji w ścieżce katalogu głównego pakietu, który wygląda następująco

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

tutaj jest plik index.js

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

Załóżmy teraz, że mamy plik defaults.json

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

i development.json tak

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

jeśli to zrobisz config = require('./config'), otrzymasz

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

Zauważ, że otrzymujesz wszystkie wartości domyślne oprócz tych zdefiniowanych w plikach specyficznych dla środowiska. Możesz więc zarządzać hierarchią konfiguracji. Używanie defaultsDeepzapewnia, że ​​możesz mieć zagnieżdżone wartości domyślne.



0

Wypróbowałem tutaj niektóre z proponowanych rozwiązań, ale nie byłem z nich zadowolony, więc stworzyłem własny moduł. Nazywa się, mikro-configa główna różnica polega na tym, że honoruje konwencję nad konfiguracją, więc możesz po prostu wymagać modułu i zacząć z niego korzystać.

Przechowujesz swoją konfigurację w zwykłych plikach js lub json z /configfolderu. Najpierw ładuje default.jsplik, następnie wszystkie inne pliki z /configkatalogu, a następnie ładuje konfigurację specyficzną dla środowiska na podstawie $NODE_ENVzmiennej.

Pozwala również zastąpić tę konfigurację dla rozwoju lokalnego local.jslub specyficznego dla środowiska /config/env/$NODE_ENV.local.js.

Możesz na to spojrzeć tutaj:

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

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


0

Przez długi czas korzystałem z podejścia wymienionego w rozwiązaniu tutaj. Istnieją jednak obawy dotyczące bezpieczeństwa tajemnic w postaci czystego tekstu. Możesz użyć innego pakietu na wierzchu, configaby zająć się bitami bezpieczeństwa.

Sprawdź to: https://www.attosol.com/secure-application-secrets-using-masterkey-in-azure-key-vault/


Dlaczego powinienem nawet subskrybować platformę Azure, aby zapłacić za tę usługę? Dlaczego nie skorzystać z ansible-vault? Kolejna sprawa: myślę, że nikt nie opublikuje pliku konfiguracyjnego z czystymi danymi uwierzytelniającymi w repozytorium źródłowym. Użyj zmiennych środowiskowych lub umieść to swoje tajne dane w pliku z uprawnieniem tylko do odczytu.
Yasser Sinjab

Jeśli możesz odczytać go z lokalizacji innej firmy i zdekodować go, a Twoja usługa użyje tych ściśle tajnych danych, haker może zrobić dokładnie to samo, jeśli uzyska dostęp do twojego komputera. To więcej pracy (trwa dłużej), ale w końcu cię nie chroni. Jeśli twój serwer został przeniknięty, wyobraź sobie, że wszystko, co masz na nim, jest teraz publiczne.
Alexis Wilke
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.