Wie speichere ich die Bereitstellungseinstellungen / Konfigurationsdateien von Node.j?

639

Ich habe an einigen Node-Apps gearbeitet und nach einem guten Muster zum Speichern von einstellungsbezogenen Einstellungen gesucht. In der Django-Welt (woher ich komme) besteht die übliche Praxis darin, eine settings.pyDatei mit den Standardeinstellungen (Zeitzone usw.) und dann eine local_settings.pyfür die Bereitstellung spezifische Einstellungen zu haben, d. H. Mit welcher Datenbank soll gesprochen werden, mit welchem ​​Memcache-Socket, welcher E-Mail-Adresse für die Administratoren und so weiter.

Ich habe nach ähnlichen Mustern für Node gesucht. Nur eine Konfigurationsdatei wäre schön, damit sie nicht mit allem anderen eingeklemmt werden muss app.js, aber ich finde es wichtig, eine Möglichkeit zu haben, eine serverspezifische Konfiguration in einer Datei zu haben, die sich nicht in der Quellcodeverwaltung befindet. Dieselbe App könnte durchaus auf verschiedenen Servern mit völlig unterschiedlichen Einstellungen bereitgestellt werden und sich mit Zusammenführungskonflikten befassen müssen, und all das ist nicht meine Vorstellung von Spaß.

Gibt es dafür eine Art Framework / Tool oder hackt jeder einfach selbst etwas zusammen?

mikl
quelle
Ich mag die Art und Weise, wie die Konfiguration in mean.js erfolgt . Im Grunde speichern sie die app-relevante Konfiguration in einer separaten Art von Modul, basierend auf unterschiedlichen Einstellungen pro App-Umgebung (für Produktion, Entwicklung, Test) und der Weitergabe spezifischer Details durch App-Umgebungsvariablen wie Geheimnisse usw.
Hinrich

Antworten:

765

Ich verwende a package.jsonfür meine Pakete und a config.jsfür meine Konfiguration, die wie folgt aussieht:

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;

Ich lade die Konfiguration aus meinem Projekt:

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

und dann kann ich meine Sachen zugreifen config.db_host, config.db_portetc ... Auf diese Weise können Sie mich entweder Gebrauch fest einprogrammierten Parameter oder Parameter in Umgebungsvariablen gespeichert , wenn ich nicht zum Speichern von Passwörtern in der Quellcodeverwaltung will.

Ich generiere auch einen package.jsonund füge einen Abhängigkeitsabschnitt ein:

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

Wenn ich das Projekt auf meinen lokalen Computer klone npm install, starte ich , um die Pakete zu installieren. Mehr Infos dazu hier .

Das Projekt wird in GitHub gespeichert und Fernbedienungen für meinen Produktionsserver hinzugefügt.

noli
quelle
32
Was passiert, wenn Sie unterschiedliche Konfigurationseinstellungen für dev vs. prod haben?
Chovy
4
Ich habe es nicht getan, aber hier ist eine Möglichkeit, dies zu tun. Legen Sie für jede Umgebung den Namen der Umgebung in einer ENV-Variablen fest. Dann ist es in dieser Datei nur Javascript. Verwenden Sie eine case- oder if-Anweisung, um die entsprechenden Variablen selektiv zu laden. Sie können sogar eine separate Konfigurationsunterdatei für jede Umgebung erstellen und in der if-Anweisung die Unterdatei hier in eine Unterkonfigurationsvariable neu laden und diese Unterkonfigurationsvariable in die Hauptkonfiguration exportieren. Ich versuche im Grunde nur zu sagen, dass sie gerecht ist js, so können Sie kreativ sein
noli
4
welcher process.env? wo befindet es sich? Und wie stellt man es ein?
wütend Kiwi
12
Ich dachte "wow ... ich habe ein paar Stunden lang auf node.js geschaut und meine App funktioniert bereits ... übrigens, vielleicht teile ich dieses zufällige Stück Code, das ich mir ausgedacht habe"
noli
3
Können Sie nicht immer noch Umgebungsvariablen verwenden, um diese Passwörter zu speichern? Ist das nicht das, wofür diese Zeile ist: config.twitter.password = process.env.TWITTER_PASSWORD || 'Passwort';
DMart
243

Sie können JSON-Dateien ab Node v0.5.x anfordern (unter Bezugnahme auf diese Antwort ).

config.json:

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

app.js:

var config = require('./config.json');
log_in(config.username, config.password);
TinyTimZamboni
quelle
40
Nicht so beeindruckt von dieser Funktion. Sie könnten ("./ config.js") benötigen und Sie können Kommentare zu Konfigurationsdateien hinzufügen, die ich für sehr wichtig halte, und andere Schnickschnack. Wenn Ihre Konfiguration nur Eigenschaften und kein Code ist, verlieren Sie nichts, indem Sie (config.js) mit Ihrem JSON mit dem Präfix exports.config =
teknopaul
3
@teknopaul Sie haben Recht, aber es gab eine große Diskussion über die 'Korrektheit' / Verwendbarkeit der Verwendung von dummen oder intelligenten Template-Systemen, die mir sagte: (1) Sie möchten normalerweise eine deklarative / dumme Sprache für Templating / Optionen (2) Es ist eine schlechte Idee, einen "Fast-PL" zu rekonstruieren, um nur Vorlagen (oder Konfigurationen) zu erstellen - besser, um Ihren vorhandenen realen PL mit bekannten Verhaltensweisen wiederzuverwenden. bisher +1 für das Recycling von JS, um Benutzereinstellungen vorzunehmen; -1 für den nicht deklarativen Ansatz. Wir haben einige ziemlich komplexe Konfigurationsaufgaben gesehen, die deklarativ durchgeführt wurden. Mein Bauch sagt mir, dass dies der richtige Weg ist.
Flow
1
Keine Intellisense für Objekte aus JSON-Dateien in VScode (Ende 2017). Voll funktionsfähiges Intellisense für Objekte aus module.exports.
Romain Vincent
199

Viel später fand ich ein ziemlich gutes Node.js-Modul zum Verwalten der Konfiguration: nconf .

Ein einfaches Beispiel:

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

Es unterstützt auch das Speichern von Einstellungen in Redis , das Schreiben von Konfigurationsdateien und verfügt über eine ziemlich solide API. Außerdem wird es von einem der angesehensten Node.js-Shops, Nodejitsu , als Teil der Flatiron- Framework-Initiative unterstützt ziemlich zukunftssicher.

Schauen Sie sich nconf bei Github an .

mikl
quelle
2
Vielleicht eine dumme Frage, aber ich habe keine klare Erklärung gesehen: Wo setze ich Knotenumgebungsvariablen? Ich verwende bereits nconf, aber es ist nicht klar, wo ich Umgebungsvariablen festlegen würde. Ist es in Nginx / Apache? Ist es eine andere Konfigurationsdatei?
Zivilist
91
Ich halte es nicht für eine gute Idee, die .json-Datei als Konfiguration zu verwenden, da Kommentare nicht zulässig sind.
Frank Xu
11
Das sieht gut aus. Ich denke, Sie werden viele Unixheads überraschen, wenn die Konfigurationsdatei Befehlszeilenoptionen und Umgebungsvariablen überschreibt. Wir sind an die folgende Reihenfolge aufsteigender Priorität gewöhnt: Konfigurationsdatei (en), Umgebungsvariablen, Befehlszeilenoptionen.
Sheldonh
2
@sheldonh Warten Sie, bis Sie herausfinden, dass boolesche Optionen immer auf argv gesetzt sind, wodurch die Priorität gebrochen wird ...: /
Daniel C. Sobral
@ DanielC.Sobral Es ist eine echte Schande. Oh, und LTNS! :-)
Sheldonh
94

Meine Lösung ist ziemlich einfach:

Laden Sie die Umgebungskonfiguration in ./config/index.js

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

module.exports = cfg;

Definieren Sie einige Standardeinstellungen in ./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';

Überschreiben Sie die Standardeinstellungen in ./config/config.test.js

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

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

module.exports = config;

Verwenden Sie es in ./models/user.js:

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

Ausführen Ihrer App in einer Testumgebung:

NODE_ENV=test node ./app.js
chovy
quelle
2
Ich bevorzuge das hier. Wie von anderen erwähnt, ist JSON keine bevorzugte Speicherstruktur und diese Überlagerung mit Globals ist einfach und effektiv
Sebastian J.
Der einzige Grund, warum ich dies nconf vorziehen würde, ist, dass es das .js-Format für Konfigurationsdateien (dev, test und prod) zulässt. So können wir jede Konfigurationsoption dokumentieren, die sonst im JSON-Format nicht möglich ist.
Kunal Kapadia
Übrigens, NODE_ENVstandardmäßig "Entwicklung". Sie sollten stattdessen nach "Produktion" suchen.
Kevin Suttle
5
Ich überprüfe nicht auf Entwicklung. Ich bin standardmäßig dabei. Ich bin mir nicht sicher, warum ich jemals standardmäßig produzieren würde.
Chovy
39

Sie können auch nach dotenv suchen, das den Grundsätzen einer Zwölf-Faktor-App folgt .

Ich habe früher node-config verwendet, aber aus diesem Grund dotenv erstellt. Es wurde vollständig von Rubys Dotenv-Bibliothek inspiriert.

Die Verwendung ist recht einfach:

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

Dann erstellen Sie einfach eine .env-Datei und geben Ihre Einstellungen wie folgt ein:

S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE
OTHER_SECRET_STUFF=my_cats_middle_name

Das ist dotenv für nodejs.

Scottmotte
quelle
2
Oder verwenden Sie foreman run node xx.jsdiese Option, um automatisch auch Ihre .env-Datei einzulesen.
Simon
1
würde ich diesen Ansatz auch für die Produktion verwenden?
Lamour
1
@lamar nein, Sie setzen sie in den env-Variablen auf dem tatsächlichen Server. Das war jedes Mal, wenn Sie sie bereitstellen, sie sind dort, aber nicht im Quellcode.
Sidonaldson
@ Lamar Ja, Sie können tatsächlich als tragbarere Alternative zum Festlegen von env-Variablen auf dem Server. Der wichtige Punkt ist , um nicht die enthält .envDatei in Ihrer Versionskontrolle oder Bereitstellungsprozess.
Josh Noe
31

Verwendet ihr npm, um eure Skripte zu starten (env etc)?

Wenn Sie .envDateien verwenden, können Sie diese in Ihre Dateien aufnehmen package.json und sie mit npm als Quelle / Start verwenden.

Beispiel:

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

Führen Sie dann die npm-Skripte aus:

$ npm start-dev

Es ist hier beschrieben https://gist.github.com/ericelliott/4152984 Alle Dank an Eric Elliot

lxx
quelle
2
Können Sie erklären, was "Quelle" ist? Ich bekommesource : not found
JohnnyBizzle
@JohnnyBizzle source(oder einfach .) ist ein in Unix-Shells (Bash usw.) integrierter Befehl zum Lesen und Ausführen von Befehlen aus der angegebenen Datei in der aktuellen Shell . Das heißt, die Befehle werden nicht in einer Unterschale ausgeführt. Dies hat in diesem Beispiel zur Folge, dass die in definierten Umgebungsvariablen prod.envzur aktuellen Shell hinzugefügt und somit an jeden untergeordneten Prozess übergeben werden, der von dieser Shell erzeugt wird. Sie scheinen Windows CMD zu verwenden. Weitere Informationen finden Sie in dieser Frage .
Utku
Bemerkenswert - 12 Faktor App empfiehlt nicht zu schaffen dev.envund prod.env, aber mit einer einzelnen .envDatei pro deploy.
Freitag,
24

Sie können sich auch die Knotenkonfiguration ansehen, die die Konfigurationsdatei abhängig von der Variablen $ HOST und $ NODE_ENV lädt (ein bisschen wie RoR): Dokumentation .

Dies kann für unterschiedliche Einsatz Einstellungen sehr nützlich sein ( development, testoder production).

ngryman
quelle
22

Mach einfach ein settings.jsmit exports:

exports.my_password = 'value'

Führen Sie dann in Ihrem Skript Folgendes aus require:

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

Alle Ihre Einstellungen sind jetzt über die settingsVariable verfügbar :

settings.my_password // 'value'
Vanuan
quelle
@backdesk Natürlich könnten Sie ein geheimes Speichersystem einrichten, das Geheimnisse verschlüsselt und den Zugriff mit IP, einigen Token usw. einschränkt. Letztendlich geht es jedoch nur darum, einige Dateien von der Festplatte zu lesen, sei es verschlüsselt oder nicht.
Vanuan
@backdesk Es gibt kein Problem mit dem Beispiel. Ist genau das: ein Beispiel für die Erklärung von etwas Konkretem.
Emilio Grisolía
14

Ich werde hier meinen Hut in den Ring werfen, weil keine dieser Antworten alle kritischen Komponenten anspricht, die so ziemlich jedes System benötigt. Überlegungen:

  • Öffentliche Konfiguration (die vom Frontend gesehen werden kann) vs. private Konfiguration (Guy Mograbi hat diese richtig verstanden). Und sicherstellen, dass diese getrennt gehalten werden.
  • Geheimnisse wie Schlüssel
  • Standardeinstellungen für umgebungsspezifische Überschreibungen
  • Frontend-Bundles

So mache ich meine Konfiguration:

  • config.default.private.js - In der Versionskontrolle sind dies Standardkonfigurationsoptionen, die nur von Ihrem Backend angezeigt werden.
  • config.default.public.js- In der Versionskontrolle sind dies Standardkonfigurationsoptionen, die vom Backend und Frontend angezeigt werden
  • config.dev.private.js - Wenn Sie andere private Standardeinstellungen für dev benötigen.
  • config.dev.public.js - Wenn Sie unterschiedliche öffentliche Standardeinstellungen für dev benötigen.
  • config.private.js - Nicht in der Versionskontrolle, dies sind umgebungsspezifische Optionen, die überschrieben werden config.default.private.js
  • config.public.js - Nicht in der Versionskontrolle, dies sind umgebungsspezifische Optionen, die überschrieben werden config.default.public.js
  • keys/- Ein Ordner, in dem jede Datei ein anderes Geheimnis speichert. Dies steht auch nicht unter Versionskontrolle (Schlüssel sollten niemals unter Versionskontrolle stehen).

Ich verwende einfache alte Javascript-Dateien für die Konfiguration, damit ich die volle Leistung der Javascript-Sprache nutzen kann (einschließlich Kommentaren und der Möglichkeit, beispielsweise die Standard-Konfigurationsdatei in die umgebungsspezifische Datei zu laden, damit sie dann überschrieben werden können). Wenn Sie Umgebungsvariablen verwenden möchten, können Sie diese in diese Konfigurationsdateien laden (obwohl ich aus dem gleichen Grund, aus dem ich die Verwendung von JSON-Dateien nicht empfehle, die Verwendung von Env-Variablen ablehne - Sie haben nicht die Fähigkeit einer Programmiersprache zum Erstellen Ihre Konfiguration).

Der Grund, warum sich jeder Schlüssel in einer separaten Datei befindet, liegt im Installationsprogramm. Auf diese Weise können Sie ein Installationsprogramm einrichten, das Schlüssel auf dem Computer erstellt und im Schlüsselordner speichert. Ohne dies kann Ihr Installationsprogramm fehlschlagen, wenn Sie Ihre Konfigurationsdatei laden, die nicht auf Ihre Schlüssel zugreifen kann. Auf diese Weise können Sie das Verzeichnis durchlaufen und alle Schlüsseldateien laden, die sich in diesem Ordner befinden, ohne sich Gedanken darüber machen zu müssen, was in einer bestimmten Version Ihres Codes vorhanden ist und was nicht.

Da Sie wahrscheinlich Schlüssel in Ihrer privaten Konfiguration geladen haben, möchten Sie Ihre private Konfiguration definitiv nicht in einen Frontend-Code laden. Während es wahrscheinlich strikt idealer ist, Ihre Frontend-Codebasis vollständig von Ihrem Backend zu trennen, ist PITA häufig eine ausreichend große Barriere, um zu verhindern, dass Benutzer dies tun, also private oder öffentliche Konfiguration. Ich tue jedoch zwei Dinge, um zu verhindern, dass private Konfigurationen in das Frontend geladen werden:

  1. Ich habe einen Komponententest, der sicherstellt, dass meine Frontend-Bundles keinen der geheimen Schlüssel enthalten, die ich in der privaten Konfiguration habe.
  2. Ich habe meinen Frontend-Code in einem anderen Ordner als meinen Backend-Code und zwei verschiedene Dateien mit dem Namen "config.js" - eine für jedes Ende. Für das Backend lädt config.js die private Konfiguration, für das Frontend lädt es die öffentliche Konfiguration. Dann benötigen Sie immer nur ('config') und machen sich keine Sorgen darüber, woher es kommt.

Eine letzte Sache: Ihre Konfiguration sollte über eine völlig separate Datei in den Browser geladen werden als jeder andere Frontend-Code. Wenn Sie Ihren Frontend-Code bündeln, sollte die öffentliche Konfiguration als vollständig separates Bundle erstellt werden. Andernfalls ist Ihre Konfiguration nicht mehr wirklich konfiguriert - sie ist nur ein Teil Ihres Codes. Die Konfiguration muss auf verschiedenen Computern unterschiedlich sein können.

BT
quelle
13

Convict ist eine weitere Option, mit der ein Schema zur Validierung hinzugefügt wird. Wie nconf unterstützt es das Laden von Einstellungen aus einer beliebigen Kombination von Umgebungsvariablen, Argumenten, Dateien und JSON-Objekten.

Beispiel aus der 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"
  }
});

Erste Schritte Artikel: Konfigurieren von Konfigurationen mit Node-Convict

Hurrymaplelad
quelle
12

Sie können Konfig für umgebungsspezifische Konfigurationsdateien verwenden. Es lädt automatisch JSON- oder YamL-Konfigurationsdateien, verfügt über Standardwerte und dynamische Konfigurationsfunktionen.

Ein Beispiel aus dem 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"
    }
}

In Entwicklung:

> config.app.port
3000

Nehmen wir in der Produktion an, wir starten die Anwendung mit $ NODE_ENV=production PORT=4567 node app.js

> config.app.port
4567

Weitere Details: https://github.com/vngrs/konfig

Ali Davut
quelle
9

Ich werde einen Ordner als Konfiguration und Dateinamen erstellen config.jsund später diese Datei verwenden, wo immer dies erforderlich ist (siehe unten)

Beispiel für config.js

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

Dann, wenn ich diese Konfigurationsdatei irgendwo verwenden möchte

Ich werde zuerst wie unten importieren

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

und ich kann auf die Werte wie folgt zugreifen

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
quelle
5

Verwenden Sie einfach das npmModul config(mehr als 300000 Downloads)

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

Node-config organisiert hierarchische Konfigurationen für Ihre App-Bereitstellungen.

Sie können eine Reihe von Standardparametern definieren und diese für verschiedene Bereitstellungsumgebungen (Entwicklung, QA, Staging, Produktion usw.) erweitern.

$ 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
alex dykyі
quelle
4

Es ist besser, die Konfigurationen "Entwicklung" und "Produktion" zu trennen.

Ich benutze folgende Methode: Hier ist meine Datei 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 : ""
        }
    }
} 

Verwenden Sie für die Konfiguration Folgendes:

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

Dann können Sie Ihr Konfigurationsobjekt verwenden:

const ip_address = config.ip_address;
const port = config.port;
Aram Manukyan
quelle
Sie können auch Benutzer module.exports = config;am Ende der config/index.jsDatei
Mapmalith
3

Ich bin etwas spät im Spiel, aber ich konnte hier oder anderswo nicht finden, was ich brauchte, also habe ich selbst etwas geschrieben.

Meine Anforderungen an einen Konfigurationsmechanismus sind folgende:

  1. Frontend unterstützen. Was ist der Punkt, wenn das Front-End die Konfiguration nicht verwenden kann?
  2. Support settings-overrides.js- sieht gleich aus, erlaubt aber Überschreibungen der Konfiguration bei settings.js. Die Idee hier ist, die Konfiguration einfach zu ändern, ohne den Code zu ändern. Ich finde es nützlich für Saas.

Auch wenn mir unterstützende Umgebungen weniger wichtig sind, wird hier erklärt, wie ich sie einfach zu meiner Lösung hinzufügen kann

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;

Erläuterung

  • undefined bedeutet, dass diese Eigenschaft erforderlich ist
  • null bedeutet, dass es optional ist
  • meConf- Derzeit ist der Code Ziel einer Datei unter app. meConfist das Überschreiben von Dateien, auf die abgezielt wird conf/dev- was von meinen vcs ignoriert wird.
  • publicConfiguration - wird vom Frontend und Backend aus sichtbar sein.
  • privateConfiguration - wird nur vom Backend aus sichtbar sein.
  • sendPublicConfiguration- Eine Route, die die öffentliche Konfiguration verfügbar macht und sie einer globalen Variablen zuweist. Der folgende Code macht beispielsweise die öffentliche Konfiguration als globale Variable myConf im Frontend verfügbar. Standardmäßig wird der globale Variablenname verwendet conf.

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

Logik der Überschreibungen

  • privateConfiguration wird mit publicConfiguration und dann mit meConf zusammengeführt.
  • publicConfiguration überprüft jeden Schlüssel auf Überschreibung und verwendet diese Überschreibung. Auf diese Weise legen wir nichts Privates offen.

Unterstützung für die Umgebung hinzufügen

Auch wenn ich eine "Umgebungsunterstützung" nicht nützlich finde, wird es vielleicht jemand tun.

Um Umgebungsunterstützung hinzuzufügen, müssen Sie die meConf require-Anweisung in etwa so ändern (Pseudocode).

if (Umwelt == "Produktion") {meConf = erfordern ("../ conf / dev / meConf"). Produktion; }}

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

Ebenso können Sie eine Datei pro Umgebung haben

 meConf.development.js
 meConf.production.js

und importiere den richtigen. Der Rest der Logik bleibt gleich.

Kerl Mograbi
quelle
nicht besonders offensichtlich, was undefinedwirklich "erforderlich" und null"optional" bedeutet. Also ist der gelbe Behälter für Plastik und der blaue für Altpapier? gut, musste aber das Handbuch lesen, bevor ich den Wurf wegwarf.
Flow
Sie müssen diese Konvention nicht verwenden. Ich finde es nützlich und weise mein Team an, es zu verwenden, aber Sie können diese Funktion natürlich entfernen.
Kerl Mograbi
3

Ein altes Beispiel, das ich gerade verwendet habe, weil ich mehr Flexibilität als eine typische .json-Datei wollte, aber nicht wollte, dass sie in eine Bibliothek abstrahiert wird, für die eine Abhängigkeit erforderlich wäre. Grundsätzlich wird eine sofort aufgerufene Funktion exportiert, die ein Objekt mit den von mir gewünschten Werten zurückgibt. Gibt viel Flexibilität.

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

Es gibt hier eine viel bessere Erklärung mit vollständigem Beispiel. Verwenden von Konfigurationsdateien in Node.js.

Kapitänavi
quelle
3

Ich weiß, dass dies ein wirklich alter Beitrag ist. Aber ich möchte mein Modul für die Konfiguration von Umgebungsvariablen freigeben. Ich denke, es ist eine sehr flexible Lösung. Hier ist das Modul json-configure

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 

Dann können Sie process.env.NODE_ENValle Variablen für Ihre Umgebung abrufen.

Christian
quelle
2

Neben dem NConf Modul in erwähnter dieser Antwort , und Knoten-config in erwähnter diese Antwort gibt es auch Knoten-iniparser und IniReader , die einfache ini - Konfigurationsdatei - Parser zu sein scheint.

Wingman4l7
quelle
Es gibt keine Möglichkeit, zu Win-Ini-Dateien zurückzukehren. iniparserDies unterstreicht stolz die Tatsache, dass sie wissen, wie man Abschnitte in der Konfiguration analysiert. 2013. Wenn Sie eine tiefere Verschachtelung benötigen, sagen Sie [foo/bar]? [foo\bar]? bar.baz=42? bar/baz=42? bar\baz=42? bar:baz=42? Wie erkennt man 42eine Zahl? Es könnte ein ganzstelliger Text sein! - Werfen Sie XML, werfen Sie YAML, werfen Sie WIN.INI, umarmen Sie JSON, die Sorgen sind weg.
Flow
1

Ich habe kürzlich ein kleines Modul veröffentlicht, um alle Arten von Konfigurationsdateien zu laden. Es ist ziemlich einfach, Sie können es unter https://github.com/flesler/config-node überprüfen

Ariel Flesler
quelle
1

Sie können pconf verwenden: https://www.npmjs.com/package/pconf

Beispiel:

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
quelle
1

Hier ist ein ordentlicher Ansatz, der von diesem Artikel inspiriert wurde . Es sind keine zusätzlichen Pakete außer dem allgegenwärtigen Lodash-Paket erforderlich . Darüber hinaus können Sie verschachtelte Standardeinstellungen mit umgebungsspezifischen Überschreibungen verwalten.

Erstellen Sie zunächst einen Konfigurationsordner im Paketstammpfad, der so aussieht

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

Hier ist die Datei index.js

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

Nehmen wir nun an, wir haben eine solche defaults.json

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

und development.json gefällt das

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

Wenn Sie config = require('./config')hier tun, werden Sie bekommen

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

Beachten Sie, dass Sie alle Standardwerte außer den in umgebungsspezifischen Dateien definierten erhalten. So können Sie eine Konfigurationshierarchie verwalten. Durch defaultsDeepdie Verwendung wird sichergestellt, dass Sie sogar verschachtelte Standardeinstellungen haben können.

Rahul
quelle
0

Ich habe hier einige Lösungsvorschläge ausprobiert, war aber nicht zufrieden damit. Deshalb habe ich mein eigenes Modul erstellt. Es wird aufgerufen mikro-configund der Hauptunterschied besteht darin, dass die Konvention gegenüber der Konfiguration berücksichtigt wird. Sie können also einfach das Modul benötigen und es verwenden.

Sie speichern Ihre Konfiguration entweder in einfachen js- oder json-Dateien aus dem /configOrdner. Zuerst wird eine default.jsDatei geladen , dann alle anderen Dateien aus dem /configVerzeichnis, dann wird die umgebungsspezifische Konfiguration basierend auf geladen$NODE_ENV Variablen geladen.

Außerdem kann diese Konfiguration für die lokale Entwicklung mit local.jsoder umgebungsspezifisch überschrieben werden /config/env/$NODE_ENV.local.js.

Sie können es hier ansehen:

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

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

Martin Adámek
quelle
0

Lange habe ich den in der Lösung hier erwähnten Ansatz verwendet. Es gibt jedoch Bedenken hinsichtlich der Sicherheit der Geheimnisse im Klartext. Sie können ein anderes Paket darüber verwendenconfig damit die Sicherheitsbits erledigt werden.

Überprüfen Sie dies: https://www.attosol.com/secure-application-secrets-using-masterkey-in-azure-key-vault/

Rahul Soni
quelle
Warum sollte ich Azure überhaupt abonnieren, um diesen Service zu bezahlen? Warum nicht ansible-vault verwenden? Eine andere Sache: Ich denke, niemand wird eine Konfigurationsdatei mit Klartext-Anmeldeinformationen im Quell-Repository veröffentlichen. Verwenden Sie entweder Umgebungsvariablen oder speichern Sie Ihre geheimen Daten in einer Datei mit schreibgeschützter Berechtigung.
Yasser Sinjab
Wenn Sie es von einem Drittanbieter lesen und dekodieren können und Ihr Dienst diese streng geheimen Daten verwenden kann, kann ein Hacker genau dasselbe tun, wenn er Zugriff auf Ihren Computer erhält. Es ist mehr Arbeit (dauert länger), aber am Ende schützt es Sie nicht. Wenn Ihr Server durchdrungen ist, stellen Sie sich vor, dass alles, was Sie darauf haben, jetzt öffentlich ist.
Alexis Wilke