Como conservar Nodo.configuração/ficheiros de configuração da implantação do js?
tenho trabalhado em alguns aplicativos de nós, e tenho procurado um bom padrão de armazenamento de configurações relacionadas com a implantação. No mundo Django( de onde eu venho), a prática comum seria ter um arquivo settings.py
contendo as configurações padrão (timezone, etc), e então um local_settings.py
para configurações específicas de implantação, ou seja. com que Base de dados falar, que socket memcache, endereço de E-mail para os administradores e assim por diante.
23 answers
Uso um package.json
para os meus pacotes e um config.js
para a 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;
Carrego a configuração do meu projecto:
var config = require('./config');
E depois posso aceder às minhas coisas de config.db_host
, config.db_port
, etc... Isto permite-me usar parâmetros hardcoded, ou parâmetros armazenados em variáveis ambientais se eu não quiser armazenar senhas no controle de fonte.
Eu também gerar um package.json
e inserir uma secçã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 clonei o projecto para a minha máquina local, Eu corro npm install
para instalar os pacotes. Mais informações sobre isso aqui.
O projecto é armazenado no GitHub, com comandos adicionados para o meu servidor de produção.
Pode necessitar de ficheiros 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);
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 em Redis , escrevendo arquivos de configuração, e tem uma API bastante sólida, e também é suportado por um dos nós mais respeitados.js shops, Nodejitsu , como parte da iniciativa-quadro Flatiron , por isso deve ser razoavelmente à prova do futuro.
Check out nconf at Github .
Carregar a configuração do ambiente ./config / index.js
var env = process.env.NODE_ENV || 'development'
, cfg = require('./config.'+env);
module.exports = cfg;
Define alguns valores por omissão ./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';
Sobrepõe os valores por omissão./config / config.teste.js
var config = require('./config.global');
config.env = 'test';
config.hostname = 'test.example';
config.mongo.db = 'example_test';
module.exports = config;
Usando-o dentro ./ models / user.js:
var mongoose = require('mongoose')
, cfg = require('../config')
, db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
A correr a aplicação no ambiente de ensaio:
NODE_ENV=test node ./app.js
Isto é explicado em maior detalhe aqui.: http://www.chovy.com/node-js/managing-config-variables-inside-a-node-js-application/
Você também pode olhar para dotenv, que segue os princípios de um doze fator app.
Eu costumava usar o nó-config, mas criei o dotenv por essa razão. Foi completamente inspirado pela biblioteca de Ruby dootenv.
A utilização é bastante fácil:
var dotenv = require('dotenv');
dotenv.load();
Então, basta criar um .env file e coloque as suas configurações aí, Assim:
S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE
OTHER_SECRET_STUFF=my_cats_middle_name
Isso é dotenv para os nodejs.
Estão a usar o npm para iniciar os vossos programas (env, etc) ?
Se usar os ficheiros .env
pode incluí-los no seu package.json
e use o npm para o código / 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": "*"
}
}
Execute então os programas do npm:
$ npm start-dev
Está descrito aqui https://gist.github.com/ericelliott/4152984 Todo o crédito ao Eric Elliot
Você também pode olhar para nó-config que carrega o arquivo de configuração, dependendo $HOST e $NODE_ENV variável (um pouco como o RoR) : documentação.
Isto pode ser bastante útil para diferentes configurações de implantação (development
, test
ou production
).
Basta fazer um simples settings.js
com exports
:
exports.my_password = 'value'
Então, no seu guião, faça um require
:
var settings = require('./settings.js');
Todas as suas configurações agora serão disponíveis via settings
variável:
settings.my_password // 'value'
O Convict é outra opção que adiciona um esquema de validação. Como nconf, ele suporta configurações de carregamento 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"
}
});
[[2]}começar o artigo:
configurações de Domamento com nó-condenado
Pode usar O Konfig para ficheiros de configuração específicos do ambiente. Ele carrega arquivos de configuração JSON ou yaml automaticamente, ele tem o valor padrão e características de configuração dinâmica.
Um exemplo do Acordo de recompra do 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
Em 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
- configuração pública (que pode ser vista pela interface) vs configuração privada (guy mograbi acertou neste). E assegurar que estes sejam mantidos separados. Segredos como chaves
- predefinições vs substituições específicas do ambiente
- pacotes Frontend
-
config.default.private.js
- no controlo de versões, estas são opções de configuração predefinidas que só podem ser vistas pela sua infra-estrutura. -
config.default.public.js
- no controlo de versões, estas são as opções de configuração predefinidas que podem ser vistas pela infra-estrutura e frontend -
config.dev.private.js
- Se precisar de diferentes padrões privados para o dev. - Se precisar de diferentes padrões públicos para o dev.
-
config.private.js
- não no controlo de versões, estas são específicas do ambiente opções que sobrepõemconfig.default.private.js
-
config.public.js
- não no controlo de versões, estas são opções específicas do ambiente que sobrepõemconfig.default.public.js
- Uma pasta onde cada ficheiro guarda um segredo diferente de algum tipo. Isto também não está sob controle de versão (chaves nunca devem estar sob controle de versão).
Uso ficheiros javascript simples para configuração, por isso tenho todo o poder do langauge javascript (incluindo comentários e a capacidade de fazer coisas como carregar o valor por omissão ficheiro de configuração no ficheiro específico do ambiente para que possam ser sobrepostos). Se você quiser usar variáveis de ambiente, você pode carregá - las dentro desses arquivos de configuração (tho eu recomendo contra o uso de vars env pela mesma razão que eu 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á num ficheiro separado é para ser usada pelo instalador. Isto permite-lhe ter um instalador que cria as chaves na máquina e guarda-as na pasta das chaves. Sem isto, o seu instalador poderá falhar quando carregar o seu ficheiro de configuração que não consegue aceder às suas chaves. Desta forma você pode atravessar o diretório e carregar qualquer arquivo 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 dada do seu código.
Dado que provavelmente tem as chaves carregadas na sua configuração privada, você definitivamente não quer carregar a sua configuração privada em nenhum código de interface. Embora provavelmente estritamente mais ideal para separar completamente a sua base de código da sua infra-estrutura, muitas vezes que a PITA é uma barreira grande o suficiente para impedir que as pessoas façam isso, assim privado vs configuração pública. Mas há duas coisas que eu faço para evitar que config privado seja carregado na frente:
-
Tenho um teste de unidade que garante que os meus pacotes frontend não contêm uma das chaves secretas que tenho na configuração privada.
Tenho o meu código de interface numa pasta diferente da minha infra-estrutura. código, e tenho dois ficheiros diferentes chamados "config".js " - um para cada extremidade. Para infra-estrutura, config.o js carrega a configuração privada, para frontend, carrega a configuração pública. Então você sempre só precisa('config') e não se preocupe sobre de onde ele vem.
Uma última coisa:a sua configuração deve ser carregada no navegador através de um completamente separado de qualquer um dos seus outros códigos de interface. Se você agrupar o seu código de interface, a configuração pública deve ser construída como um um pacote completamente separado. Caso contrário, a sua configuração já não é realmente config - é apenas parte do seu código. Config precisa ser capaz de ser diferente em máquinas diferentes.
Criarei uma pasta como configuração de um ficheiro com o nome config.js
e, mais tarde, utilizarei este ficheiro onde for necessário, conforme abaixo
Exemplo de configuração.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 este ficheiro de configuração algures
Primeiro importarei como abaixo
var config = require('./config');
E posso aceder aos valores 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');
}
});
Os meus requisitos para um mecanismo de configuração são os seguintes:
-
Suporte frontal. Qual é o ponto se o front-end não pode usar a configuração?
- Suporte
settings-overrides.js
- que parece o mesmo, mas permite sobreposições de configuração emsettings.js
. A idéia aqui é modificar a configuração facilmente sem alterar o código. Eu encontro-o. útil para saas.
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 esta propriedade é necessária -
null
significa que é opcional -
meConf
- actualmente, o código é alvo de um ficheiro emapp
.meConf
são os ficheiros de substituições que são direccionados para {[[9]} - que são ignorados pelos meus vcs. -
publicConfiguration
- será visível da frente e traseira. - - Só será visível de trás para a frente.
-
sendPublicConfiguration
- uma rota que irá expor a configuração pública e atribuí-la 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 omissão, irá usar o nome da variável globalconf
.App.get ("/backend/conf", require ("conf").sendPublicConfiguration);
Lógica de sobrepõe
- a configuração privada funde-se com a configuração pública e depois meConf.
- a configuração pública verifica cada tecla se tem uma anulação, e usa essa anulação. Assim não vamos expor nada privado.
Adicionar suporte ao ambiente
Apesar de não achar útil um "suporte ambiental", talvez alguém o faça.Para adicionar suporte de ambiente você precisa mudar o meConf precisa de declaração para algo como isto (pseudocode)
If ( Ambiente = "Produção") { meConf = require("../ conf / dev / meConf").producao; }
If (ambiente = "desenvolvimento" ) { meConf = require("../ conf / dev / meConf").desenvolvimento; }
Da mesma forma, você pode ter um arquivo por Ambiente
meConf.development.js
meConf.production.js
E importar o direito.
O resto da lógica permanece a mesma.
module.exports = function(){
switch(node_env){
case 'dev':
return
{ var1 = 'development'};
}
}();
Há uma explicação muito melhor com um exemplo completo. a usar ficheiros de configuração no nó.js
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_ENV
para obter todas as variáveis para o seu ambiente.
Além do nconf módulo mencionado no esta resposta, e nó-config mencionado no esta resposta, existem também nó-iniparser e IniReader, que parecem ser mais simples .analisadores de ficheiros de configuração ini.
Acabei de lançar um pequeno módulo para carregar qualquer tipo de ficheiros de configuração. É muito em frente, podes verificar em https://github.com/flesler/config-node
Pode utilizar 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
}
É melhor separar as configurações 'desenvolvimento' e 'Produção'.
Eu uso da seguinte forma: Aqui está a minha configuração / índice .Js ficheiro:
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 requerer a configuração, utilize o seguinte:
const config = require('../config')[process.env.NODE_ENV];
Do que pode usar o seu objecto de configuração:
const ip_address = config.ip_address;
const port = config.port;
Você guarda a sua configuração em ficheiros js simples ou json da pasta /config
. Primeiro carrega o ficheiro default.js
, Depois todos os outros ficheiros da pasta /config
, depois carrega a configuração específica do ambiente com base em $NODE_ENV
variavel.
Também permite sobrepor esta configuração para o desenvolvimento local com {[5] } ou com o ambiente específico /config/env/$NODE_ENV.local.js
.
config
para que os bits de segurança sejam tratados.
Olha para isto.https://www.attosol.com/secure-application-secrets-using-masterkey-in-azure-key-vault/
Basta utilizar npm
Módulo config
(mais de 300000 downloads)
Https://www.npmjs.com/package/config
O nó-Configuração organiza configurações hierárquicas para as suas aplicações.
Permite-lhe definir um conjunto de parâmetros predefinidos e alargá-los para diferentes ambientes de implantação (desenvolvimento, qa, encenação, 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