Como armazenar os arquivos de configuração / configuração de implantação do Node.js.

640

Eu tenho trabalhado em alguns aplicativos de Nó e tenho procurado um bom padrão de armazenamento de configurações relacionadas à implantação. No mundo do Django (de onde eu venho), a prática comum seria ter um settings.pyarquivo contendo as configurações padrão (fuso horário, etc) e, em seguida, um local_settings.pypara configurações específicas de implantação, ie. qual banco de dados conversar, qual soquete do memcache, endereço de email para os administradores e assim por diante.

Eu tenho procurado padrões semelhantes para Node. Apenas um arquivo de configuração seria bom, portanto, não precisa ser bloqueado com todo o resto app.js, mas acho importante ter uma maneira de ter uma configuração específica do servidor em um arquivo que não esteja no controle de origem. O mesmo aplicativo pode ser implantado em diferentes servidores com configurações totalmente diferentes, e ter que lidar com conflitos de mesclagem e tudo o que não é minha ideia de diversão.

Então, existe algum tipo de estrutura / ferramenta para isso, ou todos simplesmente cortam algo juntos?

mikl
fonte
Eu realmente gosto da maneira como a configuração é feita em mean.js . Basicamente, eles armazenam aplicativo de configuração relevante em uma espécie seperat de módulo, com base nas configurações diferentes por ambiente de aplicativo (para a produção, desenvolvimento, teste) e passando detalhes específicos através de variáveis de ambiente de aplicativos, como segredos etc.
Hinrich

Respostas:

765

Eu uso um package.jsonpara meus pacotes e um config.jspara minha configuração, que se parece com:

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;

Eu carrego a configuração do meu projeto:

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

e então posso acessar minhas coisas de config.db_host, config.db_portetc ... Isso me permite usar parâmetros codificados ou parâmetros armazenados em variáveis ​​ambientais, se não desejar armazenar senhas no controle de origem.

Também gero package.jsone insiro uma seção de dependências:

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

Quando clono o projeto na minha máquina local, corro npm installpara instalar os pacotes. Mais informações sobre isso aqui .

O projeto é armazenado no GitHub, com controles remotos adicionados ao meu servidor de produção.

noli
fonte
32
o que acontece quando você tem diferentes configurações para dev vs. prod?
chovy 20/09/12
4
Eu não tenho, mas aqui está uma maneira de fazê-lo .. para cada env, defina o nome do env em uma variável ENV. Então, neste arquivo, é apenas javascript .. use uma instrução case ou if para carregar seletivamente as variáveis ​​apropriadas. Você pode até criar um subarquivo de configuração separado para cada ambiente e, na instrução if, recarregar o subarquivo aqui em um subconfig var e exportar esse subconfig var para a configuração principal. Tudo o que estou basicamente tentando dizer é que é apenas js, para que possa ser criativo
noli
4
qual process.env? onde ele localiza? E como configurá-lo?
kiwi irritado
12
Eu estava pensando "uau .. eu estou olhando o node.js por algumas horas e meu aplicativo já está funcionando .. btw, talvez eu compartilhe esse bit aleatório de código que eu
criei
3
Você ainda não pode usar variáveis ​​de ambiente para armazenar essas senhas? Não é para isso que serve esta linha: config.twitter.password = process.env.TWITTER_PASSWORD || 'senha';
DMart
244

Você pode exigir arquivos JSON a partir do Nó v0.5.x ( referenciando esta resposta )

config.json:

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

app.js:

var config = require('./config.json');
log_in(config.username, config.password);
TinyTimZamboni
fonte
40
Não tão impressionado com esse recurso. Você pode precisar ("./ config.js") e poderá adicionar comentários aos arquivos de configuração que considero muito importantes, além de outros detalhes. Se você configuração é apenas propriedades e nenhum código que você solta nada por requerem (config.js) com você JSON prefixados por exports.config =
teknopaul
3
@teknopaul você está certo, mas costumava haver uma grande discussão em andamento sobre a 'correção' / usabilidade do uso de sistemas de modelos burros x inteligentes, que me diziam: (1) você normalmente quer uma linguagem declarativa / burra para modelos / opções (2) é uma má idéia reconstruir um "quase PL" para fazer apenas modelagem (ou configuração) - melhor para reutilizar seu PL real existente com comportamentos conhecidos. até agora +1 para reciclar JS para fazer configurações do usuário; -1 por não seguir a abordagem declarativa. vimos algumas coisas de configuração bastante complexas feitas da maneira declarativa; meu intestino me diz que este é o caminho a percorrer.
fluxo
1
Nenhum intellisense em objetos de arquivos json no VScode (final de 2017). Intellisense totalmente funcional para objetos de module.exports.
Romain Vincent
199

Muito mais tarde, encontrei um módulo Node.js muito bom para gerenciar a configuração: nconf .

Um exemplo simples:

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

Ele também suporta o armazenamento de configurações no Redis , a gravação de arquivos de configuração e possui uma API bastante sólida, além de ser apoiado por uma das lojas mais respeitadas do Node.js. , o Nodejitsu , como parte da iniciativa da estrutura Flatiron. razoavelmente à prova de futuro.

Confira o nconf no Github .

mikl
fonte
2
Talvez seja uma pergunta idiota, mas ainda não vi uma explicação clara: onde posso definir variáveis ​​de ambiente do nó? Eu já estou usando o nconf, mas não está claro onde eu definiria variáveis ​​ambientais. Está no nginx / apache? É outro arquivo de configuração?
Civil
91
Eu não acho que usar o arquivo .json como config é uma boa idéia, pois os comentários não são permitidos.
Frank Xu
11
Isso parece ótimo. Acho que você surpreenderá muitos Unixheads se o arquivo de configuração substituir opções de linha de comando e variáveis ​​de ambiente. Estamos acostumados à seguinte ordem de precedência crescente: arquivo (s) de configuração, variáveis ​​de ambiente, opções de linha de comando.
sheldonh
2
@sheldonh Espere até você descobrir que opções booleanas são sempre definido em argv, portanto, quebrando precedência ...: /
Daniel C. Sobral
@ DanielC.Sobral É uma pena. Ah, e LTNS! :-)
sheldonh
94

Minha solução é bastante simples:

Carregue a configuração do ambiente em ./config/index.js

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

module.exports = cfg;

Defina alguns padrões em ./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';

Substitua os padrões em ./config/config.test.js

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

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

module.exports = config;

Utilizando-o em ./models/user.js:

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

Executando seu aplicativo no ambiente de teste:

NODE_ENV=test node ./app.js
chovy
fonte
2
Eu prefiro este. Como foi referido por outros JSON não é uma estrutura de armazenamento preferida e esta estratificação com globais é simples e eficaz
Sebastian J.
A única razão pela qual eu preferiria isso sobre o nconf é porque ele permite o formato .js para arquivos de configuração (dev, test e prod). nos permitindo documentar cada opção de configuração que, de outra forma, não é possível com o formato JSON.
Kunal Kapadia
BTW, o NODE_ENVpadrão é 'desenvolvimento'. Você deve procurar por 'produção'.
quer
5
Não estou verificando o desenvolvimento. Eu estou inadimplente. Não sei por que alguma vez eu iria usar como padrão a produção.
chovy
39

Você também pode procurar o dotenv, que segue os princípios de um aplicativo de doze fatores .

Eu costumava usar o node-config, mas criei o dotenv por esse motivo. Foi completamente inspirado pela biblioteca dotenv do ruby.

O uso é bastante fácil:

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

Então você apenas cria um arquivo .env e coloca suas configurações como:

S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE
OTHER_SECRET_STUFF=my_cats_middle_name

Isso é dotenv para nodejs.

scottmotte
fonte
2
Ou simplesmente use foreman run node xx.jsisso também lerá automaticamente o seu arquivo .env.
Simon
1
eu usaria essa abordagem também para produção?
Lamour 03/07
1
@ lamar não, você os define nas variáveis ​​env no servidor real. Sempre que você implanta, eles estão lá, mas não no código-fonte.
sidonaldson
@ Lamar sim, você pode, na verdade, como uma alternativa mais portátil para definir variáveis ​​de ambiente no servidor. O ponto importante é não incluir o .envarquivo no seu controle de versão ou processo de implantação.
21717 Josh Noe
31

Vocês estão usando o npm para iniciar seus scripts (env etc)?

Se você usar .envarquivos, poderá incluí-los no seu package.json e usar o npm para fonte / iniciá-los.

Exemplo:

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

em seguida, execute os scripts npm:

$ npm start-dev

É descrito aqui https://gist.github.com/ericelliott/4152984 Todo o crédito a Eric Elliot

lxx
fonte
2
Você pode explicar o que é "fonte"? Eu recebosource : not found
JohnnyBizzle
O @JohnnyBizzle source(ou simplesmente .) é um comando interno nos shells do Unix (Bash, etc.) para ler e executar comandos do arquivo fornecido, no shell atual . Ou seja, os comandos não são executados em um sub-shell. O efeito disso neste exemplo é que as variáveis ​​de ambiente definidas em prod.envsão adicionadas ao shell atual e, portanto, passadas para qualquer processo filho gerado por esse shell. Você parece estar usando o Windows CMD. Veja esta pergunta para mais detalhes.
Utku
Vale ressaltar - o aplicativo com 12 fatores recomenda não criar dev.enve prod.env, mas ter um único .envarquivo por implantação.
Iiridayn
24

Você também pode procurar a node-config, que carrega o arquivo de configuração, dependendo da variável $ HOST e $ NODE_ENV (um pouco como a RoR): documentação .

Isso pode ser bastante útil para diferentes configurações de implantação ( development, testou production).

ngryman
fonte
22

Basta fazer um simples settings.jscom exports:

exports.my_password = 'value'

Em seu script, faça um require:

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

Todas as suas configurações agora estarão disponíveis via settingsvariável:

settings.my_password // 'value'
Vanuan
fonte
@backdesk, é claro que você poderia configurar um sistema de armazenamento secreto que criptografaria segredos e limitaria o acesso usando ip, alguns tokens, etc. não.
Vanuan
@ backdesk Não há nenhum problema com o exemplo. É exatamente isso: um exemplo para explicar algo concreto.
Emilio Grisolía
14

Vou jogar meu chapéu no ringue aqui, porque nenhuma dessas respostas aborda todos os componentes críticos que praticamente qualquer sistema precisa. Considerações:

  • Configuração pública (que pode ser vista pelo frontend) vs configuração privada (guy mograbi acertou). E garantir que eles sejam mantidos separados.
  • Segredos como chaves
  • Padrões versus substituições específicas do ambiente
  • Pacotes de front-end

Aqui está como eu faço minha configuração:

  • config.default.private.js - No controle de versão, essas são opções de configuração padrão que só podem ser vistas pelo seu back-end.
  • config.default.public.js- No controle de versão, essas são opções de configuração padrão que podem ser vistas pelo back - end e front - end
  • config.dev.private.js - Se você precisar de diferentes padrões privados para dev.
  • config.dev.public.js - Se você precisar de diferentes padrões públicos para dev.
  • config.private.js - Não no controle de versão, são opções específicas do ambiente que substituem config.default.private.js
  • config.public.js - Não no controle de versão, são opções específicas do ambiente que substituem config.default.public.js
  • keys/- Uma pasta onde cada arquivo armazena um segredo diferente de algum tipo. Isso também não está sob controle de versão (as chaves nunca devem estar sob controle de versão).

Eu uso arquivos javascript simples para configuração, para ter todo o poder do idioma javascript (incluindo comentários e a capacidade de fazer coisas como carregar o arquivo de configuração padrão no arquivo específico do ambiente para que possam ser substituídos). Se você quiser usar variáveis ​​de ambiente, poderá carregá-las dentro desses arquivos de configuração (embora eu recomendo o uso de env vars pelo mesmo motivo, não recomendo o uso de arquivos json - você não tem o poder de uma linguagem de programação para construir sua configuração).

A razão pela qual cada chave está em um arquivo separado é para uso do instalador. Isso permite que você tenha um instalador que cria chaves na máquina e as armazena na pasta de chaves. Sem isso, seu instalador pode falhar quando você carrega o arquivo de configuração que não pode acessar suas chaves. Dessa forma, você pode percorrer o diretório e carregar todos os arquivos de chave que estão nessa pasta sem ter que se preocupar com o que existe e o que não existe em qualquer versão do seu código.

Como você provavelmente tem chaves carregadas em sua configuração privada, você definitivamente não deseja carregar sua configuração privada em nenhum código de front-end. Embora seja provavelmente estritamente mais ideal separar completamente sua base de código de front-end e back-end, muitas vezes o PITA é uma barreira grande o suficiente para impedir que as pessoas o façam, portanto, configuração privada versus pública. Mas há duas coisas que faço para impedir que a configuração privada seja carregada no front-end:

  1. Eu tenho um teste de unidade que garante que meus pacotes de front-end não contenham uma das chaves secretas que tenho na configuração privada.
  2. Eu tenho meu código de front-end em uma pasta diferente do meu código de back-end e tenho dois arquivos diferentes chamados "config.js" - um para cada extremidade. Para back-end, o config.js carrega a configuração privada, para o front-end, carrega a configuração pública. Então você sempre precisa ('config') e não se preocupa com a origem.

Uma última coisa: sua configuração deve ser carregada no navegador por meio de um arquivo completamente separado do que qualquer outro código de front-end. Se você agrupar seu código de front-end, a configuração pública deverá ser construída como um pacote completamente separado. Caso contrário, sua configuração não será mais configurada - é apenas parte do seu código. O Config precisa ser diferente em máquinas diferentes.

BT
fonte
13

Convict é outra opção que adiciona um esquema para validação. Como o nconf, ele suporta o carregamento de configurações de qualquer combinação de variáveis ​​de ambiente, argumentos, arquivos e objetos json.

Exemplo do 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"
  }
});

Artigo de introdução: Domesticando configurações com node-convict

hurrymaplelad
fonte
12

Você pode usar o Konfig para arquivos de configuração específicos do ambiente. Carrega arquivos de configuração json ou yaml automaticamente, possui valor padrão e recursos de configuração dinâmica.

Um exemplo do repositório 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"
    }
}

Em desenvolvimento:

> config.app.port
3000

Na produção, suponha que começamos a aplicação com $ NODE_ENV=production PORT=4567 node app.js

> config.app.port
4567

Mais detalhes: https://github.com/vngrs/konfig

Ali Davut
fonte
9

Vou criar uma pasta como config, nomeando um arquivo config.jse, mais tarde, usarei esse arquivo sempre que necessário, conforme abaixo

Exemplo de config.js

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

Então, se eu quiser usar esse arquivo de configuração em algum lugar

Primeiro importarei como abaixo

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

e eu posso acessar os valores como abaixo

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
fonte
6

Basta usar o npmmódulo config(mais de 300000 downloads)

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

O Node-config organiza configurações hierárquicas para implantações de aplicativos.

Permite definir um conjunto de parâmetros padrão e estendê-los para diferentes ambientes de implantação (desenvolvimento, qa, preparo, produção, etc.).

$ 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і
fonte
4

É melhor separar as configurações de 'desenvolvimento' e 'produção' .

Eu uso da seguinte maneira: Aqui está o meu arquivo 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 : ""
        }
    }
} 

Para exigir a configuração, use o seguinte:

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

Do que você pode usar seu objeto de configuração:

const ip_address = config.ip_address;
const port = config.port;
Aram Manukyan
fonte
também você pode usuário module.exports = config;no final do config/index.jsarquivo
mapmalith 20/06/19
3

Estou um pouco atrasado no jogo, mas não consegui encontrar o que precisava aqui - ou em qualquer outro lugar -, então escrevi algo.

Meus requisitos para um mecanismo de configuração são os seguintes:

  1. Suporte front-end. Qual o sentido de o front-end não poder usar a configuração?
  2. Suporte settings-overrides.js- que parece o mesmo, mas permite substituições de configuração em settings.js. A idéia aqui é modificar a configuração facilmente, sem alterar o código. Acho útil para saas.

Mesmo que eu me importe menos com ambientes de suporte - o explicará como adicioná-lo facilmente à minha solução

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;

Explicação

  • undefined significa que essa propriedade é necessária
  • null significa que é opcional
  • meConf- atualmente o código é direcionado para um arquivo em app. meConfsão os arquivos de substituição direcionados a conf/dev- que são ignorados pelos meus vcs.
  • publicConfiguration - ficará visível no front-end e no back-end.
  • privateConfiguration - ficará visível apenas no back-end.
  • sendPublicConfiguration- uma rota que exporá a configuração pública e a atribuirá a uma variável global. Por exemplo, o código abaixo irá expor a configuração pública como variável global myConf no front-end. Por padrão, ele usará o nome da variável global conf.

    app.get ("/ back-end / conf", require ("conf"). sendPublicConfiguration);

Lógica de substituições

  • privateConfiguration é mesclado com publicConfiguration e depois meConf.
  • publicConfiguration verifica cada chave se houver uma substituição e usa essa substituição. Dessa forma, não estamos expondo nada de particular.

Adicionando suporte ao ambiente

Mesmo que eu não ache um "suporte ao ambiente" útil, talvez alguém o encontre.

Para adicionar suporte ao ambiente, você precisa alterar a instrução de requisição meConf para algo assim (pseudocódigo)

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

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

Da mesma forma, você pode ter um arquivo por ambiente

 meConf.development.js
 meConf.production.js

e importe o caminho certo. O restante da lógica permanece o mesmo.

guy mograbi
fonte
não é terrivelmente óbvio que undefinedrealmente significa 'obrigatório' e nullsignifica 'opcional'. então a lixeira amarela é para plásticos e a azul é para papel de rascunho? tudo bem, mas tive que ler o manual antes de jogar a areia.
fluxo
Você não precisa usar esta convenção. Acho útil e instruo minha equipe a usá-lo, mas você pode obviamente remover esse recurso.
cara Mograbi
3

um exemplo alt que acabei de usar porque queria mais flexibilidade do que um arquivo .json típico, mas não queria que ele fosse abstraído para uma biblioteca que exigiria uma dependência é algo como isto. Basicamente, exportar uma função chamada imediatamente que retornou um objeto com os valores que eu queria definir. Dá muita flexibilidade.

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

Há uma explicação muito melhor com exemplo completo aqui. Usando arquivos de configuração no Node.js

captainavi
fonte
3

Eu sei que este é um post muito antigo. Mas eu quero compartilhar meu módulo para configurar variáveis ​​de ambiente, acho que é uma solução muito flexível. Aqui está o módulo 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 

Então você pode usar process.env.NODE_ENVpara obter todas as variáveis ​​para o seu ambiente.

cristão
fonte
2

Além do módulo nconf mencionado nesta resposta e do node-config mencionado nesta resposta , também existem o node-iniparser e o IniReader , que parecem ser analisadores de arquivo de configuração .ini mais simples.

Wingman4l7
fonte
não há como voltar aos arquivos win-ini ... que iniparserenfatizam orgulhosamente o fato de saberem analisar seções na configuração ... em 2013 ... se você precisar de um aninhamento mais profundo, você diz [foo/bar]? [foo\bar]? bar.baz=42? bar/baz=42? bar\baz=42? bar:baz=42? como você diz 42é um número? pode ser um texto com todos os dígitos!
fluxo
1

Você pode usar o pconf: https://www.npmjs.com/package/pconf

Exemplo:

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

Aqui está uma abordagem elegante, inspirada neste artigo . Ele não requer nenhum pacote adicional, exceto o onipresente pacote lodash . Além disso, permite gerenciar padrões aninhados com substituições específicas do ambiente.

Primeiro, crie uma pasta de configuração no caminho raiz do pacote que se parece com isso

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

aqui está o arquivo index.js

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

Agora vamos supor que temos um defaults.json assim

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

e development.json assim

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

se você fizer config = require('./config')aqui é o que você receberá

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

Observe que você obtém todos os valores padrão, exceto aqueles definidos em arquivos específicos do ambiente. Então você pode gerenciar uma hierarquia de configuração. O uso defaultsDeepgarante que você possa ter padrões aninhados.

Rahul
fonte
0

Tentei algumas das soluções sugeridas aqui, mas não fiquei satisfeito com elas, então criei meu próprio módulo. Ele é chamado mikro-confige a principal diferença é que ele respeita as convenções sobre a configuração, para que você possa apenas precisar do módulo e começar a usá-lo.

Você armazena sua configuração em arquivos js simples ou json da /configpasta. Primeiro, ele carrega o default.jsarquivo, depois todos os outros arquivos do /configdiretório e, em seguida, carrega a configuração específica do ambiente com base na $NODE_ENVvariável.

Também permite substituir essa configuração para desenvolvimento local local.jsou específico do ambiente /config/env/$NODE_ENV.local.js.

Você pode dar uma olhada aqui:

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

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

Martin Adámek
fonte
0

Por muito tempo, eu costumava usar a abordagem mencionada na solução aqui. No entanto, existe uma preocupação com a segurança dos segredos em texto não criptografado. Você pode usar outro pacote em cima configpara que os bits de segurança sejam resolvidos.

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

Rahul Soni
fonte
Por que devo me inscrever no Azure para pagar por esse serviço? Por que não usar o ansible-vault? Outra coisa: acho que ninguém publicará um arquivo de configuração com credenciais de texto não criptografado no repositório de origem. Use variáveis ​​de ambiente ou coloque seus dados secretos em um arquivo com permissão somente leitura.
Yasser Sinjab
Se você puder lê-lo em algum local de terceiros, decodificá-lo e fazer com que seu serviço use esses dados extremamente secretos, um hacker poderá fazer exatamente o mesmo se tiver acesso ao seu computador. É mais trabalho (leva mais tempo), mas no final não o protege. Se o seu servidor for invadido, imagine que tudo o que você tem agora seja público.
Alexis Wilke