Node.js mettant en place des configurations spécifiques à l'environnement à utiliser avec everyauth

117

J'utilise node.js + express.js + everyauth.js. J'ai déplacé toute ma logique everyauth dans un fichier de module

var login = require('./lib/everyauthLogin');

à l'intérieur, je charge mon fichier de configuration oAuth avec les combinaisons clé / secret:

var conf = require('./conf');
.....
twitter: {
    consumerKey: 'ABC', 
    consumerSecret: '123'
}

Ces codes sont différents pour différents environnements - développement / pré-production / production car les rappels sont vers des URL différentes.

Qu. Comment puis-je définir ces paramètres dans la configuration d'environnement pour filtrer tous les modules ou puis-je passer le chemin directement dans le module?

Définir dans env:

app.configure('development', function(){
  app.set('configPath', './confLocal');
});

app.configure('production', function(){
  app.set('configPath', './confProduction');
});

var conf = require(app.get('configPath'));

Passer

app.configure('production', function(){
  var login = require('./lib/everyauthLogin', {configPath: './confProduction'});
});

? j'espère que cela a du sens

andy t
la source
J'ai trouvé une solution qui utilise certaines des idées ci-dessous, en ayant le module = function plutôt qu'un objet, je peux évaluer process.env.NODE_ENV et renvoyer l'objet correct pour l'environnement. Un peu en désordre mais fonctionne.
andy t
Pardonnez l'auto-promotion éhontée, mais j'ai écrit un module pour node.js qui le fera via des fichiers séparés et un commutateur de ligne de commande: node-configure
Randolpho

Réponses:

192

Ma solution,

charger l'application en utilisant

NODE_ENV=production node app.js

Puis configurer config.jscomme une fonction plutôt que comme un objet

module.exports = function(){
    switch(process.env.NODE_ENV){
        case 'development':
            return {dev setting};

        case 'production':
            return {prod settings};

        default:
            return {error or other settings};
    }
};

Ensuite, selon la solution Jans, chargez le fichier et créez une nouvelle instance que nous pourrions transmettre une valeur si nécessaire, dans ce cas, elle process.env.NODE_ENVest globale, donc inutile.

var Config = require('./conf'),
    conf = new Config();

Ensuite, nous pouvons accéder aux propriétés de l'objet de configuration exactement comme avant

conf.twitter.consumerKey
andy t
la source
2
Pourquoi utilisez-vous nouveau ici?
bluehallu
5
Je seconde @bluehallu. Est newnécessaire?
Chanté le
2
l'équivalent dans Windows serait SET NODE_ENV = development
mujaffars
3
Au lieu de faire new. Je suis le suivant dans config.js...Config = function(){...}; module.exports = Config()
Atu
Et si j'avais 50 serveurs Web, auquel cas il sera difficile de passer à chaque serveur pour lancer manuellement le script
Rajesh
60

Vous pouvez également avoir un fichier JSON avec NODE_ENV comme niveau supérieur. IMO, c'est une meilleure façon d'exprimer les paramètres de configuration (par opposition à l'utilisation d'un script qui renvoie les paramètres).

var config = require('./env.json')[process.env.NODE_ENV || 'development'];

Exemple pour env.json:

{
    "development": {
        "MONGO_URI": "mongodb://localhost/test",
        "MONGO_OPTIONS": { "db": { "safe": true } }
    },
    "production": {
        "MONGO_URI": "mongodb://localhost/production",
        "MONGO_OPTIONS": { "db": { "safe": true } }
    }
}
Mattwad
la source
Bonjour, pourriez-vous s'il vous plaît expliquer pourquoi vous pensez que c'est la meilleure façon d'exprimer les paramètres de configuration (par opposition à l'utilisation d'un script qui renvoie les paramètres). ?
Venkat Kotra
14
Je suppose que cela ne fait pas trop de différence. Mentalement, quand je vois JSON, je pense que les `` données statiques '' vs quand je vois un fichier JS, je pense qu'il y a une logique à l'intérieur. En outre, un autre avantage de l'utilisation du type .json est que d'autres langues peuvent importer le même fichier.
mattwad
1
Configuration @VenkatKotra est généralement considéré comme statique, et donc mieux exprimé déclarative avec des choses comme JSON, YAML, ini, etc. Fait impérieusement, avec un script qui donne cet état, sortof implique quelque chose de dynamique qui se passe, ce qui serait mauvais.
max
9
Sachez que cette méthode expose les informations d'identification dans le contrôle de code source.
Pier-Luc Gendreau
puis-je créer une URL différente pour la mise en scène et la production?
Alex le
35

Une solution très utile est d'utiliser le module config .

après avoir installé le module:

$ npm install config

Vous pouvez créer un fichier de configuration default.json . (vous pouvez utiliser un objet JSON ou JS en utilisant l'extension .json5)

Par exemple

$ vi config/default.json

{
  "name": "My App Name",
  "configPath": "/my/default/path",
  "port": 3000
}

Cette configuration par défaut peut être remplacée par un fichier de configuration d'environnement ou un fichier de configuration local pour un environnement de développement local:

production.json pourrait être:

{
  "configPath": "/my/production/path",
  "port": 8080
}

development.json pourrait être:

{
  "configPath": "/my/development/path",
  "port": 8081
}

Dans votre PC local, vous pouvez avoir un fichier local.json qui remplace tout l'environnement, ou vous pouvez avoir une configuration locale spécifique comme local-production.json ou local-development.json .

La liste complète de l'ordre de chargement .

À l'intérieur de votre application

Dans votre application, il vous suffit d'exiger la configuration et l'attribut nécessaire.

var conf = require('config'); // it loads the right file
var login = require('./lib/everyauthLogin', {configPath: conf.get('configPath'));

Chargez l'application

chargez l'application en utilisant:

NODE_ENV=production node app.js

ou définir l'environnement correct avec forever ou pm2

Pour toujours:

NODE_ENV=production forever [flags] start app.js [app_flags]

PM2 (via shell):

export NODE_ENV=staging
pm2 start app.js

PM2 (via .json):

process.json

{
   "apps" : [{
    "name": "My App",
    "script": "worker.js",
    "env": {
      "NODE_ENV": "development",
    },
    "env_production" : {
       "NODE_ENV": "production"
    }
  }]
}

Puis

$ pm2 start process.json --env production

Cette solution est très propre et permet de définir facilement différents fichiers de configuration pour l'environnement de production / de préparation / développement et pour les paramètres locaux.

Zauker
la source
npm install config --save, ce n'est pas mieux?
stackdave
15

En bref

Ce type de configuration est simple et élégant:

env.json

{
  "development": {
      "facebook_app_id": "facebook_dummy_dev_app_id",
      "facebook_app_secret": "facebook_dummy_dev_app_secret",
  }, 
  "production": {
      "facebook_app_id": "facebook_dummy_prod_app_id",
      "facebook_app_secret": "facebook_dummy_prod_app_secret",
  }
}

common.js

var env = require('env.json');

exports.config = function() {
  var node_env = process.env.NODE_ENV || 'development';
  return env[node_env];
};

app.js

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

var facebook_app_id = config.facebook_app_id;
// do something with facebook_app_id

Pour exécuter en mode production: $ NODE_ENV=production node app.js


En détail

Cette solution est de: http://himanshu.gilani.info/blog/2012/09/26/bootstraping-a-node-dot-js-app-for-dev-slash-prod-environment/ , vérifiez-le pour plus de détails.

kris
la source
5

La façon dont nous faisons cela consiste à transmettre un argument lors du démarrage de l'application avec l'environnement. Par exemple:

node app.js -c dev

Dans app.js, nous chargeons ensuite dev.jsnotre fichier de configuration. Vous pouvez analyser ces options avec optparse-js .

Maintenant, vous avez quelques modules de base qui dépendent de ce fichier de configuration. Lorsque vous les écrivez comme tels:

var Workspace = module.exports = function(config) {
    if (config) {
         // do something;
    }
}

(function () {
    this.methodOnWorkspace = function () {

    };
}).call(Workspace.prototype);

Et vous pouvez l'appeler ensuite app.jscomme:

var Workspace = require("workspace");
this.workspace = new Workspace(config);
Jan Jongboom
la source
Je préférerais garder toute la logique à l'intérieur du app.configure('developmentcode app.js , mais jetterai un coup d'œil pour voir si je peux utiliser cette solution avec cela
ety t
Mettez à jour cette réponse: Architect est un cadre de gestion des dépendances qui résout ce problème d'une manière plus agréable.
Jan Jongboom
5

Une manière élégante consiste à utiliser un .envfichier pour remplacer localement les paramètres de production. Pas besoin de commutateurs de ligne de commande. Pas besoin de toutes ces virgules et crochets dans un config.jsonfichier. Voir ma réponse ici

Exemple: sur ma machine, le .envfichier est le suivant:

NODE_ENV=dev
TWITTER_AUTH_TOKEN=something-needed-for-api-calls

Mon local .envremplace toutes les variables d'environnement. Mais sur les serveurs de préparation ou de production (peut-être sur heroku.com), les variables d'environnement sont prédéfinies pour la scène NODE_ENV=stageou la production NODE_ENV=prod.

Benxamin
la source
4

définir la variable d'environnement dans le serveur de déploiement (ex: comme NODE_ENV = production). Vous pouvez accéder à votre variable d'environnement via process.env.NODE_ENV. Recherchez le fichier de configuration suivant pour les paramètres globaux

const env = process.env.NODE_ENV || "development"

const configs = {
    base: {
        env,
        host: '0.0.0.0',
        port: 3000,
        dbPort: 3306,
        secret: "secretKey for sessions",
        dialect: 'mysql',
        issuer : 'Mysoft corp',
        subject : '[email protected]',
    },
    development: {
        port: 3000,
        dbUser: 'root',
        dbPassword: 'root',

    },
    smoke: {
        port: 3000,
        dbUser: 'root',
    },
    integration: {
        port: 3000,
        dbUser: 'root',
    },
    production: {
        port: 3000,
        dbUser: 'root',
    }
};

const config = Object.assign(configs.base, configs[env]);

module.exports= config;

base contient une configuration commune pour tous les environnements.

puis importez dans d'autres modules comme

const config =  require('path/to/config.js')
console.log(config.port)

Codage heureux ...

ajaykumar mp
la source
3

Que diriez-vous de le faire d'une manière beaucoup plus élégante avec le module nodejs-config .

Ce module est capable de définir l'environnement de configuration en fonction du nom de votre ordinateur. Après cela, lorsque vous demandez une configuration, vous obtiendrez une valeur spécifique à l'environnement.

Par exemple, supposons que vous ayez deux machines de développement nommées pc1 et pc2 et une machine de production nommée pc3. Chaque fois que vous demandez des valeurs de configuration dans votre code dans pc1 ou pc2, vous devez obtenir la configuration de l'environnement de «développement» et dans pc3, vous devez obtenir la configuration de l'environnement de «production». Ceci peut être réalisé comme ceci:

  1. Créez un fichier de configuration de base dans le répertoire config, disons "app.json" et ajoutez-y les configurations requises.
  2. Maintenant, créez simplement des dossiers dans le répertoire de configuration qui correspondent au nom de votre environnement, dans ce cas "développement" et "production".
  3. Ensuite, créez les fichiers de configuration que vous souhaitez remplacer et spécifiez les options pour chaque environnement dans les répertoires d'environnement (notez que vous n'avez pas à spécifier toutes les options qui se trouvent dans le fichier de configuration de base, mais uniquement les options que vous souhaitez remplacer. les fichiers de configuration d'environnement "cascade" sur les fichiers de base.).

Créez maintenant une nouvelle instance de configuration avec la syntaxe suivante.

var config = require('nodejs-config')(
   __dirname,  // an absolute path to your applications 'config' directory
   {
      development: ["pc1", "pc2"],
      production: ["pc3"],

   }
);

Vous pouvez maintenant obtenir n'importe quelle valeur de configuration sans vous soucier de l'environnement comme ceci:

config.get('app').configurationKey;
Harish Anchu
la source
0

Cette réponse n'est pas quelque chose de nouveau. C'est similaire à ce que @andy_t a mentionné. Mais j'utilise le modèle ci-dessous pour deux raisons.

  1. Mise en œuvre propre sans dépendances npm externes

  2. Fusionnez les paramètres de configuration par défaut avec les paramètres basés sur l'environnement.

Implémentation Javascript

const settings = {
    _default: {
       timeout: 100
       baseUrl: "http://some.api/",
    },
    production: {
       baseUrl: "http://some.prod.api/",
    },
}
// If you are not using ECMAScript 2018 Standard
// https://stackoverflow.com/a/171256/1251350
module.exports = { ...settings._default, ...settings[process.env.NODE_ENV] }

J'utilise généralement du tapuscrit dans mon projet de nœud. Voici ma mise en œuvre réelle copiée.

Implémentation du typographie

const settings: { default: ISettings, production: any } = {
    _default: {
        timeout: 100,
        baseUrl: "",
    },
    production: {
        baseUrl: "",
    },
}

export interface ISettings {
    baseUrl: string
}

export const config = ({ ...settings._default, ...settings[process.env.NODE_ENV] } as ISettings)
Faraj Farook
la source