Как сохранить настройки / файлы конфигурации Node.js?

Я работал над несколькими приложениями Node, и я искал хороший образец хранения настроек, связанных с развертыванием. В мире Django (откуда я пришел) общая практика заключалась бы в том, чтобы файл settings.py содержал стандартные настройки (часовой пояс и т. Д.), А затем local_settings.py для конкретных настроек развертывания, т.е. с какой базой данных обращаться, какой сокет memcache, адрес электронной почты для администраторов и т. д.

Я искал аналогичные шаблоны для узла. Просто файл конфигурации будет приятным, поэтому его не нужно app.js со всем остальным в app.js , но я считаю важным иметь способ конфигурации сервера в файле, который не находится в исходном управлении. Одно и то же приложение может быть развернуто на разных серверах с совершенно разными настройками и иметь дело с конфликтами слияния, и все это не является моей идеей веселья.

Так есть ли какая-то структура / инструмент для этого, или все просто взломали что-то вместе?

    Я использую package.json для своих пакетов и config.js для моей конфигурации, которая выглядит так:

     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; 

    Я загружаю конфигурацию из своего проекта:

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

    а затем я могу получить доступ к своим вещам из config.db_host , config.db_port и т. д. Это позволяет мне использовать жестко заданные параметры или параметры, хранящиеся в переменных окружения, если я не хочу хранить пароли в исходном управлении.

    Я также package.json и вставляю раздел зависимостей:

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

    Когда я клонирую проект на свой локальный компьютер, я запускаю npm install для установки пакетов. Подробнее об этом здесь .

    Проект хранится в GitHub, с добавлением пультов для моего производственного сервера.

    Вы можете потребовать файлы JSON с узла V0.5.x ( ссылаясь на этот ответ )

    config.json:

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

    app.js:

     var config = require('./config.json'); log_in(config.username, config.password); 

    Много позже я нашел довольно хороший Node.js модуль для управления конфигурацией: nconf .

    Простой пример:

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

    Он также поддерживает сохранение настроек в Redis , запись файлов конфигурации и наличие довольно прочного API, а также поддержка одного из наиболее уважаемых магазинов Node.js, Nodejitsu , как часть инициативы Flatiron framework, поэтому она должна быть справедливо будущее-доказательство.

    Проверьте nconf в Github .

    Мое решение довольно просто:

    Загрузите конфигурацию среды в ./config/index.js

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

    Определите некоторые значения по умолчанию ./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'; 

    Переопределить значения по умолчанию в ./config/config.test.js

     var config = require('./config.global'); config.env = 'test'; config.hostname = 'test.example'; config.mongo.db = 'example_test'; module.exports = config; 

    Используя его в ./models/user.js:

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

    Запуск приложения в тестовой среде:

     NODE_ENV=test node ./app.js 

    Это объясняется более подробно здесь: http://www.chovy.com/node-js/managing-config-variables-inside-a-node-js-application/

    Вы также можете посмотреть на dotenv, который следует принципам двенадцатифакторного приложения .

    Я использовал для использования node-config, но по этой причине создал dotenv. Это было полностью вдохновлено библиотекой ruby’s dotenv.

    Использование довольно просто:

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

    Затем вы просто создаете файл .env и устанавливаете свои настройки таким образом:

     S3_BUCKET=YOURS3BUCKET SECRET_KEY=YOURSECRETKEYGOESHERE OTHER_SECRET_STUFF=my_cats_middle_name 

    Это dotenv для nodejs.

    Вы, ребята, используете npm для запуска своих скриптов (env и т. Д.)?

    Если вы используете файлы .env вы можете включить их в свой package.json и использовать npm для их запуска / запуска.

    Пример:

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

    затем запустите скрипты npm:

     $ npm start-dev 

    Описанный здесь https://gist.github.com/ericelliott/4152984 Весь кредит Эрику Эллиоту

    Вы также можете посмотреть на node-config, который загружает конфигурационный файл в зависимости от переменной $ HOST и $ NODE_ENV (немного как RoR): документация .

    Это может быть весьма полезно для разных параметров развертывания ( development , test или production ).

    Просто выполните простые settings.js с exports :

     exports.my_password = 'value' 

    Затем в вашем скрипте выполните следующие действия:

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

    Теперь все ваши настройки будут доступны через переменную settings :

     settings.my_password // 'value' 

    Convict – это еще один вариант, который добавляет схему для проверки. Как и nconf, он поддерживает загрузку параметров из любой комбинации переменных среды, аргументов, файлов и json-объектов.

    Пример из 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" } }); 

    Начало работы: Укрощение конфигураций с узлом-осужденным

    Вы можете использовать Konfig для конфигурационных файлов, специфичных для среды. Он автоматически загружает файлы конфигурации json или yaml, имеет значения по умолчанию и динамические параметры конфигурации.

    Пример из репозитория 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" } } 

    В развитие:

     > config.app.port 3000 

    В процессе производства предположим, что мы запускаем приложение с $ NODE_ENV=production PORT=4567 node app.js

     > config.app.port 4567 

    Подробнее: https://github.com/vngrs/konfig

    Я собираюсь бросить свою шляпу на ринг здесь, потому что ни один из этих ответов не касается всех критических компонентов, которые в значительной степени нужны любой системе. Соображения:

    • Публичная конфигурация (которая может быть видна интерфейсом) против частной конфигурации (парень mograbi получил это право). И обеспечение их сохранения раздельно.
    • Секреты, как ключи
    • Значения по умолчанию против переопределения среды
    • Фундаментальные связки

    Вот как я делаю свою конфигурацию:

    • config.default.private.js В управлении версиями это параметры конфигурации по умолчанию, которые можно увидеть только на вашем сервере.
    • config.default.public.js – В управлении версиями это параметры конфигурации по умолчанию, которые можно увидеть с помощью backend и frontend
    • config.dev.private.js – Если вам нужны разные частные значения по умолчанию для dev.
    • config.dev.public.js – Если вам нужны разные общедоступные значения по умолчанию для dev.
    • config.private.js – не в управлении версиями, это параметры, специфичные для среды, которые переопределяют config.default.private.js
    • config.public.js – не в управлении версиями, это специальные параметры среды, которые переопределяют config.default.public.js
    • keys/ – папка, в которой каждый файл хранит другой секрет. Это также не относится к управлению версиями (ключи никогда не должны находиться под контролем версий).

    Я использую простые javascript-файлы для конфигурации, поэтому у меня есть полная мощность javascript langauge (включая комментарии и возможность делать такие вещи, как загрузка файла конфигурации по умолчанию в файл, зависящий от среды, чтобы затем их можно было переопределить). Если вы хотите использовать переменные среды, вы можете загружать их внутри этих файлов конфигурации (я рекомендую не использовать env vars по той же причине, что и я не рекомендую использовать json-файлы – у вас нет возможности языка программирования для построения ваш конфиг).

    Причина, по которой каждый ключ находится в отдельном файле, предназначен для использования установщиком. Это позволяет иметь установщик, который создает ключи на компьютере и сохраняет их в папке с ключами. Без этого ваш установщик может выйти из строя при загрузке файла конфигурации, который не может получить доступ к вашим ключам. Таким образом, вы можете перемещаться по каталогу и загружать любые файлы ключей, находящиеся в этой папке, не беспокоясь о том, что существует, а что нет в какой-либо конкретной версии вашего кода.

    Поскольку у вас, вероятно, есть ключи, загруженные в вашу личную конфигурацию, вы определенно не хотите загружать свою приватную конфигурацию в любой внешний код. В то время как его, вероятно, строго более совершенный, чтобы полностью отделять вашу внутреннюю кодовую базу от вашего бэкэнда, много раз, что PITA является достаточно большим барьером, чтобы препятствовать тому, чтобы люди это делали, таким образом, частное и общедоступное. Но есть две вещи, которые я делаю, чтобы предотвратить загрузку приватной конфигурации в интерфейсе:

    1. У меня есть единичный тест, который гарантирует, что мои интерфейсные пакеты не содержат один из секретных ключей, которые у меня есть в приватной конфигурации.
    2. У меня есть код внешнего интерфейса в другой папке, чем мой внутренний код, и у меня есть два разных файла с именем «config.js» – по одному для каждого конца. Для бэкэнд config.js загружает приватную конфигурацию, для внешнего интерфейса он загружает общедоступную конфигурацию. Тогда вы всегда просто требуете («config») и не беспокойтесь о том, откуда он.

    Последнее: ваша конфигурация должна быть загружена в браузер через совершенно отдельный файл, чем любой другой ваш внешний код. Если вы связываете свой внешний код, общедоступная конфигурация должна быть построена как совершенно отдельный пакет. В противном случае ваша конфигурация больше не является конфигурацией – ее просто частью вашего кода. Конфигурация должна быть разной на разных машинах.

    Я создам папку как конфигурацию имен файлов как config.js а позже я буду использовать этот файл там, где это необходимо, как config.js ниже.

    Пример config.js

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

    Тогда, если я хочу использовать этот файл конфигурации где-нибудь

    Я сначала импортирую, как показано ниже.

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

    и я могу получить доступ к значениям ниже

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

    Я немного опаздываю в игре, но я не мог найти то, что мне здесь нужно, или где-нибудь еще – поэтому я сам что-то написал.

    Мои требования к механизму конфигурации следующие:

    1. Поддержка интерфейса. В чем смысл, если интерфейс не может использовать конфигурацию?
    2. settings-overrides.js поддержки settings-overrides.js – которые выглядят одинаково, но позволяют переопределять конфигурацию в settings.js . Идея здесь состоит в том, чтобы легко модифицировать конфигурацию без изменения кода. Я считаю это полезным для саамов.

    Несмотря на то, что мне больше не нужна поддержка среды – объясню, как легко добавить ее к моему решению

     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; 

    объяснение

    • undefined означает, что это свойство требуется
    • null означает, что это необязательно
    • meConf – в настоящий момент код предназначен для файла в app . meConf – это файлы переопределений, предназначенные для conf/dev которые мои vcs игнорируют.
    • publicConfiguration – будет видна из интерфейсного и back-end.
    • privateConfiguration – будет видна только из privateConfiguration .
    • sendPublicConfiguration – маршрут, который будет публиковать публичную конфигурацию и назначать ее глобальной переменной. Например, приведенный ниже код откроет публичную конфигурацию как глобальную переменную myConf в интерфейсе. По умолчанию используется глобальное имя переменной conf .

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

    Логика переопределений

    • privateConfiguration объединяется с publicConfiguration, а затем meConf.
    • publicConfiguration проверяет каждый ключ, если он имеет переопределение, и использует это переопределение. Таким образом, мы не раскрываем ничего частного.

    Добавление поддержки среды

    Даже если я не нахожу «поддержку среды» полезной, возможно, кто-то будет.

    Чтобы добавить поддержку среды, вам нужно изменить инструкцию meConf require на что-то вроде этого (псевдокод)

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

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

    Аналогично, вы можете иметь файл в среде

      meConf.development.js meConf.production.js 

    и импортировать правильный. Остальная логика остается прежней.

    пример alt, который я использовал, потому что мне нужна была больше гибкости, чем типичный .json-файл, но он не хотел, чтобы он был отброшен в библиотеку, которая потребует зависимости, что-то вроде этого. В принципе, экспорт функции, вызванной немедленно, которая вернула объект со значениями, которые я хотел установить. Дает большую гибкость.

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

    Здесь приведено более полное объяснение. Использование файлов конфигурации в Node.js

    Я знаю, что это действительно старый пост. Но я хочу поделиться своим модулем для настройки переменных среды, я думаю, что это очень гибкое решение. Вот модуль 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 

    Затем вы можете использовать process.env.NODE_ENV чтобы получить все переменные для вашей среды.

    В дополнение к модулю nconf, указанному в этом ответе , и node-config, упомянутому в этом ответе , есть также node-iniparser и IniReader , которые кажутся более простыми.

    Недавно я выпустил небольшой модуль для загрузки любых файлов конфигурации. Это довольно прямолинейно, вы можете проверить его на странице https://github.com/flesler/config-node

    Вы можете использовать pconf: https://www.npmjs.com/package/pconf

    Пример:

     var Config = require("pconf"); var testConfig = new Config("testConfig"); testConfig.onload = function(){ testConfig.setValue("test", 1); testConfig.getValue("test"); //testConfig.saveConfig(); Not needed } 

    Для тех, кто посещает эту старую нить, вот пакет, который я считаю хорошим.

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

    Я попробовал некоторые из предлагаемых решений здесь, но не был им недоволен, поэтому создал собственный модуль. Он называется mikro-config и основное отличие состоит в том, что он соблюдает соглашение по конфигурации, поэтому вы можете просто потребовать модуль и начать его использовать.

    Вы сохраняете свою конфигурацию как в простых js, так и в json-файлах из папки /config . Сначала он загружает файл default.js , затем все остальные файлы из каталога /config , затем он загружает конфигурацию, специфичную для среды, на $NODE_ENV переменной $NODE_ENV .

    Он также позволяет переопределить эту конфигурацию для локальной разработки с использованием local.js или среды /config/env/$NODE_ENV.local.js .

    Вы можете взглянуть на него здесь:

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

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

    Долгое время я использовал подход, упомянутый в решении здесь. Однако существует озабоченность по поводу безопасности секретов в ясном тексте. Вы можете использовать другой пакет поверх config чтобы обеспечить безопасность битов безопасности.

    Проверьте это: https://www.attosol.com/secure-application-secrets-using-masterkey-in-azure-key-vault/

    Лучше отделить конфигурации «разработка» и «производство» .

    Я использую следующий способ: Вот мой файл 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 : "" } } } 

    Для использования конфигурации необходимо следующее:

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

    Чем вы можете использовать свой конфигурационный объект:

     const ip_address = config.ip_address; const port = config.port; 

    Просто используйте config модуля npm (более 300000 загрузок)

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

    Node-config организует иерархические конфигурации для развертывания вашего приложения.

    Он позволяет вам определить набор параметров по умолчанию и расширить их для разных сред развертывания (разработка, qa, постановка, производство и т. Д.).

     $ 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 
    Давайте будем гением компьютера.