1. Hard code
Hard code é provavelmente a forma mais "suja" de fazer isso, basicamente consiste em você escrever em algum ponto aleatório de sua app as configs dela, não importa se você deixa comentado bonitinho, ainda será a mais suja e vai ficar cada vez mais difícil de escalar, um simples exemplo:
// ...
const { Client } = require("pg");
// configs {
const httpPort = 9000;
const saltRounds = 4;
const jwtSecret = "SECRET! #tmj :D";
const psqlConfig = "postgres://localhost:5432/codeinaction_login_area";
// } <-- configs
const app = express();
// ...
Consegue ver problemas caso usemos um ambiente para dev e outro para prod? Teriamos que colocar alguns ifs malucos aí no meio e o pior poderia ser quando um novo dev entrar para o time, não faça isso para uma app do mundo real!
2. Arquivo de configuração
Outra forma comum de passar configurações é o uso de arquivos específicos de configuração, essa é uma maneira mais limpa que hard code e pode até ser usada para apps em produção desde que seja feito com prudência (e amor e carinho :)).
Um arquivo de configuração pode ser tanto um .js
ou .json
, aconselho o uso do JavaScript ao
invés de JSON pois nesse caso não precisamos nos preocupar com a formatação
exata do JSON e ainda podemos usar alguma lógica ali dentro
(mas cuidado! não coloque lógicas em arquivos de configurações! Porém, alguma
vezes podemos precisar de lógicas bem simples ou até mesmo do uso de vars
como __dirname
, nesses casos é
aceitável e o JS te da um vantagem.)
Um config.js
, geralmente se parecerá com isso:
module.exports = {
publicPath: "./public",
dbConfig: {
user: "foo",
password: "bar",
database: "codeinaction"
}
}
Podemos usar arquivos de configurações basicamente de duas formas:
1) Pré configurando uma lista de ambientes e arquivos de configurações.
2) Passando na command line de inicio do app o caminho para o arquivo de configurações.
Da primeira forma podemos fazer algo como:
const configPath = process.env.NODE_ENV === "PROD" ? "config.prod" : "config.local";
const config = require(configPath);
Ou um pouco mais limpo e com mais opções:
function getConfigPath () {
switch (process.env.NODE_ENV) {
case "prod": return "config.prod";
case "local": return "config.local";
case "dev": return "config.dev";
}
throw new Error("Unknown env");
}
const config = require(getConfigPath());
Curiosidade: em ambos os casos estamos usando env vars, você não precisa necessariamente usá-las para carregar o arquivo de config, mas nesse caso você terá que achar outro jeito de identificar o ambiente, o que nos leva a segunda forma de usar arquivos de configurações.
Passar o path do arquivo de configuração é uma forma ainda mais limpa de passar a config para sua app, evita ifs no código e você pode mover o arquivo de configuração para onde quiser.
Para usar essa tática, vamos usar o process.argv
,
podemos tanto usar ele direto e parsearmos na mão os args, ou podemos usar algum
módulo de forma que podemos passar facilmente um
-c configPath
.
Vamos ver um simples exemplo usando o minimist:
const argv = require("minimist")(process.argv.slice(2));
const config = require(argv.c);
A usage ficaria assim:
node app.js -c /my-config-path/is-here/config.local.js
Mais fácil, né?
3. Variáveis de Ambiente
Variável de ambiente se tornou um padrão na comunidade Node.js, principalmente com o surgimento de containers como o Docker.
Definição de variável de ambiente segundo Wikipedia: "Variável de ambiente é uma variável de um sistema operacional que geralmente contém informações sobre o sistema, caminhos de diretórios específicos no sistema de arquivos e as preferências do utilizador. Ela pode afetar a forma como um processo se comporta, e cada processo pode ler e escrever variáveis de ambiente".
Na construção de containers, fica mais fácil simplesmente passar as variáveis
de ambiente do que ter que se preocupar com command line ou arquivos de
configuração, outra vantagem é que você pode tanto usar algum modulo
(como o dotenv) para carregar
um arquivo chamado .env
ou definir diretamente
no seu ambiente.
Uma prática comum para o uso de env vars é comitarmos no repo um file
chamado .env.sample
, com um exemplo
de todas as variáveis que tem que ser configurada e deixar no
.gitignore
o .env
,
dessa forma, todo dev que for trabalhar no projeto ou ambiente que for
configurado, basta copiarmos esse file e editar para as configurações
específicas.
Um .env
file se parece com:
DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3
E caso você esteja usando o dotenv, a única coisa que você vai ter que fazer para carregar esse arquivo vai ser:
require("dotenv").config()
Thats it!
Caso você não queira usar um arquivo, você pode definir as vars diretamente, em um sistema UNIX (OSX/Linux), basta você mandar diretamente no console:
export DB_HOST=localhost
export DB_USER=root
export DB_PASS=s1mpl3
Porém, dessa forma as variáveis ficam disponíveis apenas para a sessão
atual, caso você feche a janela ou reinicie, elas vão sumir, você ainda
pode colocar elas em seu .bashrc
Todas as variáveis de ambiente ficam disponíveis no Node.js pelo
process.env
, exemplo:
db.connect({
host: process.env.DB_HOST,
username: process.env.DB_USER,
password: process.env.DB_PASS
})