วิธีการจัดเก็บการตั้งค่าการปรับใช้ / ไฟล์การกำหนดค่าของ Node.js


640

ฉันทำงานกับแอพ Node บางตัวและฉันกำลังมองหารูปแบบที่ดีในการจัดเก็บการตั้งค่าที่เกี่ยวข้องกับการปรับใช้ ในโลก Django (ที่ฉันมาจาก) การปฏิบัติทั่วไปจะต้องมีsettings.pyไฟล์ที่มีการตั้งค่ามาตรฐาน (เขตเวลา ฯลฯ ) จากนั้น a local_settings.pyสำหรับการปรับใช้การตั้งค่าเฉพาะเช่น ฐานข้อมูลใดที่จะคุยด้วยซ็อกเก็ต memcache ใดที่อยู่อีเมลสำหรับผู้ดูแลระบบและอื่น ๆ

ฉันได้มองหารูปแบบที่คล้ายกันสำหรับโหนด เพียงไฟล์ปรับแต่งจะดีดังนั้นจึงไม่จำเป็นต้องติดขัดกับทุกอย่างในapp.jsนั้น แต่ฉันคิดว่ามันสำคัญที่จะต้องมีวิธีกำหนดค่าเฉพาะเซิร์ฟเวอร์ในไฟล์ที่ไม่ได้อยู่ในแหล่งควบคุม แอพเดียวกันสามารถนำไปใช้กับเซิร์ฟเวอร์ที่แตกต่างกันด้วยการตั้งค่าที่แตกต่างกันอย่างดุเดือดและต้องจัดการกับความขัดแย้งที่ผสานกันและสิ่งที่ฉันคิดว่าไม่ใช่เรื่องสนุก

ดังนั้นจึงมีกรอบ / เครื่องมือบางอย่างสำหรับเรื่องนี้หรือทุกคนแค่แฮกบางอย่างเข้าด้วยกัน


ผมชอบวิธีการกำหนดค่าที่จะทำในmean.js โดยทั่วไปพวกเขาเก็บแอปกำหนดค่าที่เกี่ยวข้องในการจัดเรียง seperat ของโมดูลขึ้นอยู่กับการตั้งค่าที่แตกต่างกันต่อสภาพแวดล้อมของแอป (สำหรับการผลิต, การพัฒนา, การทดสอบ) และส่งผ่านรายละเอียดเฉพาะผ่านแอปพลิเคตัวแปรสภาพแวดล้อมเช่นความลับ ฯลฯ
Hinrich

คำตอบ:


765

ฉันใช้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ฯลฯ ... สิ่งนี้ทำให้ฉันสามารถใช้พารามิเตอร์ hardcoded หรือพารามิเตอร์ที่เก็บไว้ในตัวแปรสภาพแวดล้อมหากฉันไม่ต้องการเก็บรหัสผ่านในการควบคุมแหล่งที่มา

ฉันยังสร้าง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 พร้อมรีโมทเพิ่มสำหรับเซิร์ฟเวอร์ที่ใช้งานจริงของฉัน


32
จะเกิดอะไรขึ้นเมื่อคุณมีการตั้งค่า config ที่แตกต่างกันสำหรับ dev vs. prod
chovy

4
ฉันยังไม่ได้ แต่นี่เป็นวิธีเดียวที่จะทำได้ .. สำหรับแต่ละ env ให้ตั้งชื่อ env ในตัวแปร ENV จากนั้นในไฟล์นี้เพียงแค่จาวาสคริปต์ .. ใช้เคสหรือหากคำสั่งเพื่อเลือกโหลดตัวแปรที่เหมาะสม คุณสามารถสร้างไฟล์ย่อย config แยกกันสำหรับแต่ละ env และในคำสั่ง if โหลดไฟล์ย่อยที่นี่ลงใน subconfig var และส่งออก subconfig var ไปยัง config หลัก .. ฉันพยายามพูดว่ามันเป็นเพียงแค่ js ดังนั้นคุณจึงสามารถมีความคิดสร้างสรรค์ได้
noli

4
กระบวนการอะไร env? มันอยู่ที่ไหน และวิธีการตั้งค่า?
กีวีโกรธ

12
ฉันคิดว่า "ว้าว .. ฉันได้ดูที่ node.js สองสามชั่วโมงและแอปของฉันทำงานแล้ว .. btw บางทีฉันอาจจะแบ่งปันรหัสแบบสุ่มนี้ฉันมาด้วย"
noli

3
คุณไม่สามารถใช้ตัวแปรสภาพแวดล้อมเพื่อเก็บคำผ่านเหล่านั้นได้หรือไม่ ไม่ใช่สิ่งที่บรรทัดนี้มีไว้สำหรับ: config.twitter.password = process.env.TWITTER_PASSWORD || 'รหัสผ่าน';
DMart

244

คุณสามารถต้องการไฟล์ JSON ตั้งแต่ Node v0.5.x ( อ้างอิงคำตอบนี้ )

config.json:

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

app.js:

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

40
ไม่ค่อยประทับใจกับฟีเจอร์นี้ คุณอาจต้องการ ("./ config.js") และคุณจะได้รับความสามารถในการเพิ่มความคิดเห็นในไฟล์กำหนดค่าซึ่งฉันพิจารณาว่าสำคัญมากและเสียงระฆังและนกหวีดอื่น ๆ หากคุณกำหนดค่าเป็นคุณสมบัติเพียงอย่างเดียวและไม่มีรหัสที่คุณไม่ต้องทำสิ่งใดโดยต้องการ (config.js) กับคุณ JSON นำหน้าด้วย exports.config =
teknopaul

3
@teknopaul คุณพูดถูก แต่เคยมีการพูดคุยกันอย่างมากเกี่ยวกับ 'ความถูกต้อง' / การใช้งานของการใช้ระบบใบ้กับสมาร์ทเทมเปิลติ้งที่บอกฉันว่า: (1) โดยทั่วไปแล้วคุณต้องการภาษา (2) เป็นความคิดที่ดีที่จะสร้าง "เกือบ -pl" เพื่อทำ templating (หรือการกำหนดค่า) - ดีกว่าเพื่อใช้ PL จริงที่มีอยู่ของคุณอีกครั้งพร้อมกับพฤติกรรมที่รู้จัก ในตอนนี้ +1 สำหรับการรีไซเคิล JS เพื่อทำการตั้งค่าผู้ใช้ -1 สำหรับการไม่ไปสู่วิธีการประกาศ เราเคยเห็นบางสิ่งที่ซับซ้อน config สวยทำวิธีประกาศ; ไส้ของฉันบอกฉันว่านี่เป็นวิธีที่จะไป
flow

1
ไม่มีการรวมเข้ากับวัตถุจากไฟล์ json ใน VScode (สิ้นสุด 2017) ใช้งาน Intellisense อย่างเต็มที่สำหรับวัตถุจากโมดูลส่งออก
Romain Vincent

199

มากต่อมาผมพบว่าดีโมดูล 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ดังนั้นจึงควร พิสูจน์ได้ในอนาคต

ตรวจสอบnconf ที่ Github


2
อาจเป็นคำถามที่โง่ แต่ฉันไม่เห็นคำอธิบายที่ชัดเจน: ฉันจะตั้งค่าตัวแปรสภาพแวดล้อมของโหนดได้ที่ไหน ฉันใช้ nconf อยู่แล้ว แต่ไม่ชัดเจนว่าจะตั้งค่าตัวแปรสภาพแวดล้อมได้ที่ไหน มันอยู่ใน nginx / apache? เป็นไฟล์กำหนดค่าอื่นหรือไม่
พลเรือน

91
ฉันไม่คิดว่าใช้ไฟล์. json เนื่องจาก config เป็นความคิดที่ดีเนื่องจากไม่อนุญาตให้แสดงความคิดเห็น
แฟรงค์ Xu

11
มันดูดีมาก ฉันคิดว่าคุณจะแปลกใจกับ Unixheads มากมายหากไฟล์ config แทนที่ตัวเลือกบรรทัดคำสั่งและตัวแปรสภาพแวดล้อม เราคุ้นเคยกับลำดับความสำคัญที่ตามมาดังต่อไปนี้: ไฟล์ config ตัวแปรสภาพแวดล้อมตัวเลือกบรรทัดคำสั่ง
sheldonh

2
@sheldonh รอจนกว่าคุณจะพบว่าตัวเลือกแบบบูลจะเสมอตั้งอยู่บน argv จึงหมดความสำคัญ ... : /
แดเนียลซี Sobral

@ DanielC.Sobral มันน่าอายจริง ๆ โอ้และ LTNS! :-)
sheldonh

94

โซลูชันของฉันค่อนข้างง่าย:

โหลดการกำหนดค่าสภาพแวดล้อมใน. / 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

2
ฉันชอบอันนี้ ดังที่ผู้อื่นกล่าวถึง JSON ไม่ใช่โครงสร้างการจัดเก็บข้อมูลที่ต้องการและการฝังรากลึกด้วยกลมนี้เป็นเรื่องง่ายและมีประสิทธิภาพ
เซบาสเตียนเจ.

เหตุผลเดียวที่ฉันต้องการมากกว่านี้ nconf เป็นเพราะอนุญาตให้ฟอร์แมต. js สำหรับไฟล์ config (dev, test and prod) ช่วยให้เราสามารถจัดทำเอกสารแต่ละตัวเลือกการกำหนดค่าซึ่งเป็นไปไม่ได้ด้วยรูปแบบ JSON
Kunal Kapadia

BTW NODE_ENVเริ่มต้นที่ 'การพัฒนา' คุณควรตรวจสอบ 'การผลิต' แทน
Kevin Suttle

5
ฉันไม่ได้ตรวจสอบเพื่อการพัฒนา ฉันเริ่มต้นมัน ไม่แน่ใจว่าทำไมฉันจะเริ่มต้นการผลิต
chovy

39

นอกจากนี้คุณยังอาจมองไปdotenvซึ่งต่อไปนี้หลักการของการเป็นแอปพลิเคสิบสองปัจจัย

ฉันเคยใช้ node-config แต่สร้าง dotenv ด้วยเหตุผลนั้น มันได้รับแรงบันดาลใจมาจากห้องสมุด dotenv ของ ruby

การใช้งานค่อนข้างง่าย:

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

จากนั้นคุณเพียงแค่สร้างไฟล์. env และวางการตั้งค่าไว้ในนั้นโดยทำดังนี้

S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE
OTHER_SECRET_STUFF=my_cats_middle_name

นั่นคือdotenvสำหรับ nodejs


2
หรือเพียงแค่ใช้foreman run node xx.jsสิ่งนี้จะอ่านไฟล์. env ของคุณโดยอัตโนมัติ
ไซม่อน

1
ฉันจะใช้วิธีนี้ในการผลิตด้วยหรือไม่
Lamour

1
@lamar ไม่คุณตั้งค่าไว้ในตัวแปร env บนเซิร์ฟเวอร์จริง นั่นคือทุกครั้งที่คุณปรับใช้พวกเขาอยู่ที่นั่น แต่ไม่ได้อยู่ในซอร์สโค้ด
sidonaldson

@ Lamar ใช่คุณสามารถทำได้จริง ๆ เป็นทางเลือกแบบพกพามากกว่าการตั้งค่าตัวแปร env บนเซิร์ฟเวอร์ จุดสำคัญคือไม่รวม.envไฟล์ในการควบคุมเวอร์ชันหรือกระบวนการปรับใช้ของคุณ
Josh Noe

31

พวกคุณใช้ 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 เครดิตทั้งหมดของ Eric Elliot


2
คุณช่วยอธิบายว่า "แหล่งที่มา" คืออะไร? ฉันได้รับsource : not found
JohnnyBizzle

@JohnnyBizzle source(หรือเพียง.) คือในตัวคำสั่งในเปลือกหอย Unix (ทุบตี ฯลฯ ) เพื่ออ่านและรันคำสั่งจากไฟล์ที่กำหนดในเปลือกปัจจุบัน นั่นคือคำสั่งจะไม่ถูกดำเนินการใน sub-shell ผลกระทบของสิ่งนั้นในตัวอย่างนี้คือตัวแปรสภาพแวดล้อมที่กำหนดไว้prod.envจะถูกเพิ่มลงในเชลล์ปัจจุบันและส่งผ่านไปยังกระบวนการลูกใด ๆ ที่เกิดจากเชลล์นี้ คุณดูเหมือนจะใช้ Windows CMD ดูคำถามนี้สำหรับรายละเอียดเพิ่มเติม
Utku

น่าสังเกต - แอพ 12 ตัวแนะนำไม่สร้างdev.envและprod.envมี.envไฟล์เดียวต่อการปรับใช้
Iiridayn

24

คุณอาจมองไปที่node-configซึ่งโหลดไฟล์กำหนดค่าทั้งนี้ขึ้นอยู่กับตัวแปร$ HOSTและ$ NODE_ENV (เล็กน้อยเช่น RoR): เอกสารประกอบเอกสาร

นี้จะมีประโยชน์มากสำหรับการตั้งค่าการใช้งานที่แตกต่างกัน ( development, testหรือproduction)


22

ทำง่ายๆsettings.jsด้วยexports:

exports.my_password = 'value'

จากนั้นในสคริปต์ของคุณให้ทำrequire:

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

ขณะนี้การตั้งค่าทั้งหมดของคุณจะถูกใช้ผ่านsettingsตัวแปร:

settings.my_password // 'value'

@ backdesk แน่นอนคุณสามารถตั้งค่าระบบจัดเก็บข้อมูลลับซึ่งจะเข้ารหัสลับและ จำกัด การเข้าถึงโดยใช้ ip, โทเค็นบางอย่าง ฯลฯ แต่ในตอนท้ายของวันมันทั้งหมดมาเพียงแค่อ่านไฟล์จากดิสก์ไม่ว่าจะเป็นการเข้ารหัสหรือ ไม่.
Vanuan

@backdesk ไม่มีปัญหากับตัวอย่าง เป็นเพียงแค่: ตัวอย่างสำหรับการอธิบายสิ่งที่เป็นรูปธรรม
Emilio Grisolía

14

ฉันจะโยนหมวกของฉันลงในวงแหวนที่นี่เพราะไม่มีคำตอบใด ๆ ที่กล่าวถึงองค์ประกอบที่สำคัญทั้งหมดที่ระบบของเราต้องการ การพิจารณา:

  • การกำหนดค่าสาธารณะ (ที่สามารถเห็นได้โดยส่วนหน้า) กับการกำหนดค่าส่วนตัว (คนที่แต่งตัวประหลาด mograbi ได้สิ่งนี้ถูกต้อง) และทำให้มั่นใจว่าสิ่งเหล่านี้จะถูกแยกออกจากกัน
  • ความลับเหมือนกุญแจ
  • ค่าเริ่มต้นเทียบกับการแทนที่เฉพาะสภาพแวดล้อม
  • การรวมกลุ่มส่วนหน้า

นี่คือวิธีการกำหนดค่าของฉัน:

  • config.default.private.js - ในการควบคุมเวอร์ชันนี้เป็นตัวเลือกการกำหนดค่าเริ่มต้นที่สามารถมองเห็นได้โดยแบ็กเอนด์ของคุณ
  • config.default.public.js- ในการควบคุมเวอร์ชันนี้เป็นตัวเลือกการกำหนดค่าเริ่มต้นที่แบ็กเอนด์และสามารถมองเห็นได้ส่วนหน้า
  • 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 (รวมถึงความคิดเห็นและความสามารถในการทำสิ่งต่าง ๆ เช่นโหลดไฟล์กำหนดค่าเริ่มต้นในไฟล์เฉพาะสภาพแวดล้อมเพื่อให้สามารถแทนที่ได้) หากคุณต้องการใช้ตัวแปรสภาพแวดล้อมคุณสามารถโหลดมันไว้ในไฟล์ปรับแต่งเหล่านั้นได้ (ฉันขอแนะนำให้ใช้ env vars ด้วยเหตุผลเดียวกับที่ฉันไม่แนะนำให้ใช้ไฟล์ json - คุณไม่มีพลังในการเขียนโปรแกรมภาษา การกำหนดค่าของคุณ)

เหตุผลที่แต่ละคีย์อยู่ในไฟล์แยกต่างหากสำหรับการใช้งานตัวติดตั้ง สิ่งนี้ช่วยให้คุณมีตัวติดตั้งที่สร้างกุญแจบนเครื่องและเก็บไว้ในโฟลเดอร์คีย์ หากไม่มีตัวติดตั้งของคุณอาจล้มเหลวเมื่อคุณโหลดไฟล์กำหนดค่าที่ไม่สามารถเข้าถึงคีย์ของคุณได้ วิธีนี้คุณสามารถสำรวจไดเรกทอรีและโหลดไฟล์สำคัญใด ๆ ที่อยู่ในโฟลเดอร์นั้นโดยไม่ต้องกังวลว่ามีอยู่จริงและสิ่งใดที่ไม่ได้อยู่ในรหัสรุ่นของคุณ

เนื่องจากคุณอาจมีคีย์ที่โหลดในการกำหนดค่าส่วนตัวของคุณแน่นอนคุณไม่ต้องการโหลดการตั้งค่าส่วนตัวในรหัสส่วนหน้าใด ๆ ในขณะที่มันอาจเหมาะอย่างยิ่งที่จะแยก codebase ส่วนหน้าของคุณออกจากแบ็กเอนด์ของคุณอย่างสมบูรณ์หลายครั้งที่ PITA เป็นกำแพงกั้นที่ใหญ่พอที่จะป้องกันไม่ให้ผู้คนทำเช่นนั้น แต่มีสองสิ่งที่ฉันต้องทำเพื่อป้องกันไม่ให้โหลดการกำหนดค่าส่วนตัวในส่วนหน้า:

  1. ฉันมีการทดสอบหน่วยเพื่อให้แน่ใจว่าชุดข้อมูลส่วนหน้าของฉันไม่ได้มีหนึ่งในรหัสลับที่ฉันมีในการตั้งค่าส่วนตัว
  2. ฉันมีรหัสส่วนหน้าของฉันในโฟลเดอร์ที่แตกต่างจากรหัสด้านหลังของฉันและฉันมีสองไฟล์ที่แตกต่างกันชื่อ "config.js" - หนึ่งสำหรับแต่ละปลาย สำหรับแบ็กเอนด์ config.js โหลดการตั้งค่าส่วนตัวสำหรับส่วนหน้ามันโหลดการตั้งค่าสาธารณะ จากนั้นคุณก็แค่ต้องการ ('config') และไม่ต้องกังวลว่ามันจะมาจากไหน

สิ่งสุดท้ายสิ่งหนึ่ง: การกำหนดค่าของคุณควรโหลดลงในเบราว์เซอร์ผ่านไฟล์แยกกันโดยสมบูรณ์กว่าโค้ดส่วนหน้าอื่น ๆ ของคุณ หากคุณรวมรหัสส่วนหน้าของคุณไว้การกำหนดค่าสาธารณะควรสร้างเป็นชุดข้อมูลแยกต่างหากอย่างสมบูรณ์ มิฉะนั้นการกำหนดค่าของคุณไม่ได้กำหนดค่าจริง ๆ อีกต่อไป - เป็นเพียงส่วนหนึ่งของรหัสของคุณ การกำหนดค่าจะต้องสามารถแตกต่างกันในเครื่องที่แตกต่างกัน


13

นักโทษเป็นอีกหนึ่งตัวเลือกที่เพิ่มสคีมาสำหรับการตรวจสอบความถูกต้อง เช่นเดียวกับ 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"
  }
});

บทความเริ่มต้น: กำหนดค่าการทำให้เชื่องด้วย node-convict


12

คุณสามารถใช้Konfigสำหรับไฟล์กำหนดค่าเฉพาะสภาพแวดล้อม โหลดไฟล์กำหนดค่า json หรือ yaml โดยอัตโนมัติมีค่าเริ่มต้นและคุณสมบัติการกำหนดค่าแบบไดนามิก

ตัวอย่างจาก repo 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


9

ฉันจะสร้างโฟลเดอร์เป็นการตั้งชื่อไฟล์เป็น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');
    }
});

6

เพียงใช้npmโมดูลconfig(ดาวน์โหลดมากกว่า 300,000 ครั้ง)

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

4

มันจะดีกว่าที่จะแยก'พัฒนา'และ'ผลิต' configs

ฉันใช้วิธีต่อไปนี้: นี่คือไฟล์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;

คุณสามารถใช้งานmodule.exports = config;ในตอนท้ายของconfig/index.jsไฟล์ได้ด้วย
mapmalith

3

ฉันมาสายนิดหน่อยในเกม แต่ฉันไม่สามารถหาสิ่งที่ฉันต้องการที่นี่หรือที่อื่น - ดังนั้นฉันจึงเขียนอะไรบางอย่างด้วยตัวเอง

ข้อกำหนดของฉันสำหรับกลไกการกำหนดค่ามีดังต่อไปนี้:

  1. รองรับส่วนหน้า จะเกิดอะไรขึ้นถ้าส่วนหน้าไม่สามารถใช้การตั้งค่าได้?
  2. สนับสนุนsettings-overrides.js- ซึ่งมีลักษณะเดียวกัน settings.jsแต่ช่วยให้การแทนที่ของการกำหนดค่าที่ แนวคิดที่นี่คือการปรับเปลี่ยนการตั้งค่าได้อย่างง่ายดายโดยไม่ต้องเปลี่ยนรหัส ฉันคิดว่ามันมีประโยชน์สำหรับ 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;

คำอธิบาย

  • undefined หมายความว่าจำเป็นต้องใช้คุณสมบัตินี้
  • null หมายความว่ามันเป็นทางเลือก
  • meConf - ปัจจุบันรหัสเป็นเป้าหมายของไฟล์ภายใต้ appขณะนี้รหัสเป็นเป้าหมายไปยังแฟ้มภายใต้ meConfเป็นไฟล์แทนที่ซึ่งเป็นเป้าหมายconf/dev- ซึ่งถูกละเว้นโดย vcs ของฉัน
  • publicConfiguration - จะสามารถมองเห็นได้จาก front-end และ back-end
  • privateConfiguration - จะมองเห็นได้จากส่วนหลังเท่านั้น
  • sendPublicConfiguration- เส้นทางที่จะเปิดเผยการกำหนดค่าสาธารณะและกำหนดให้กับตัวแปรทั่วโลก ตัวอย่างเช่นรหัสด้านล่างจะเปิดเผยการกำหนดค่าสาธารณะเป็นตัวแปรทั่วโลก myConf ในส่วนหน้า โดยค่าเริ่มต้นมันจะใช้ชื่อตัวแปรทั่วโลกconfโดยค่าเริ่มต้นจะใช้ชื่อตัวแปรโลก

    app.get ("/ backend / conf", ต้องการ ("conf"). sendPublicConfiguration);

ตรรกะของการแทนที่

  • privateConfiguration ถูกรวมเข้ากับ publicConfiguration แล้ว meConf
  • publicConfiguration ตรวจสอบแต่ละคีย์ว่ามีการแทนที่และใช้การแทนที่นั้น ด้วยวิธีนี้เราจะไม่เปิดเผยสิ่งที่เป็นส่วนตัว

การเพิ่มการสนับสนุนสภาพแวดล้อม

แม้ว่าฉันจะไม่พบว่า "การสนับสนุนด้านสิ่งแวดล้อม" มีประโยชน์ แต่อาจมีบางคนต้องการ

ในการเพิ่มการสนับสนุนด้านสิ่งแวดล้อมคุณต้องเปลี่ยน meConf ต้องการข้อความสั่งเป็นบางสิ่งเช่นนี้ (pseudocode)

if (environment == "production") {meConf = ต้องการ ("../ conf / dev / meConf") การผลิต; }

if (environment == "development") {meConf = ต้องการ ("../ conf / dev / meConf"). development; }

ในทำนองเดียวกันคุณสามารถมีไฟล์ต่อสภาพแวดล้อม

 meConf.development.js
 meConf.production.js

และนำเข้าสิ่งที่ถูกต้อง ส่วนที่เหลือของตรรกะยังคงเหมือนเดิม


ไม่ชัดเจนมากว่าundefinedหมายถึง 'จำเป็น' และnullหมายถึง 'ตัวเลือก' ดังนั้นถังขยะสีเหลืองสำหรับพลาสติกและสีน้ำเงินสำหรับเศษกระดาษ? สบายดี แต่ต้องอ่านคู่มือก่อนที่จะทิ้งขยะ
ไหล

คุณไม่จำเป็นต้องใช้ระเบียบนี้ ฉันพบว่ามีประโยชน์และฉันสั่งให้ทีมของฉันใช้งาน แต่คุณสามารถลบคุณลักษณะนี้ได้อย่างชัดเจน
ผู้ชาย mograbi

3

ตัวอย่าง alt ที่ฉันเพิ่งใช้เพราะฉันต้องการความยืดหยุ่นมากกว่าไฟล์. json ทั่วไป แต่ไม่ต้องการให้มันแยกออกเป็นไลบรารีซึ่งจะต้องมีการพึ่งพาคืออะไรแบบนี้ โดยทั่วไปการส่งออกฟังก์ชั่นที่เรียกใช้ในทันทีซึ่งส่งคืนวัตถุที่มีค่าที่ฉันต้องการตั้ง ให้ความยืดหยุ่นมาก

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

มีคำอธิบายที่ดีขึ้นมากมายพร้อมตัวอย่างเต็มรูปแบบที่นี่ การใช้ไฟล์กำหนดค่าใน Node.js


3

ฉันรู้ว่านี่เป็นโพสต์เก่าจริงๆ แต่ฉันต้องการแชร์โมดูลของฉันเพื่อกำหนดค่าตัวแปรสภาพแวดล้อมฉันคิดว่ามันเป็นโซลูชันที่ยืดหยุ่นมาก นี่คือโมดูล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เพื่อรับตัวแปรทั้งหมดสำหรับสภาพแวดล้อมของคุณ


2

นอกเหนือจากโมดูล nconf ที่กล่าวถึงในคำตอบนี้และnode-config ที่กล่าวถึงในคำตอบนี้ยังมีnode-iniparserและIniReaderซึ่งดูเหมือนจะเป็นตัวแยกวิเคราะห์ไฟล์การกำหนดค่า. ini ที่ง่ายกว่า


ไม่มีทางที่จะกลับไปชนะ INI ไฟล์ ... ที่iniparserภาคภูมิใจที่เน้นความเป็นจริงที่พวกเขารู้วิธีที่จะแยกส่วนในการตั้งค่า ... ในปี 2013 ... ถ้าคุณต้องการความลึกรังทำคุณพูด[foo/bar]? [foo\bar]? bar.baz=42? bar/baz=42? bar\baz=42? bar:baz=42? คุณบอกได้อย่างไรว่า42เป็นตัวเลข? อาจเป็นข้อความตัวเลขทั้งหมด! - โยน XML, โยน YAML, โยน WIN.INI, โอบกอด JSON, หมดกังวล
flow



1

นี่คือวิธีการที่เรียบร้อยแรงบันดาลใจจากบทความนี้ ไม่จำเป็นต้องมีแพ็คเกจเพิ่มเติมยกเว้นแพ็คเกจlodash ที่แพร่หลายแพคเกจนอกจากนี้ยังช่วยให้คุณจัดการค่าเริ่มต้นที่ซ้อนกันด้วยการเขียนทับเฉพาะสภาพแวดล้อม

ก่อนอื่นให้สร้างโฟลเดอร์ปรับแต่งในเส้นทางของแพ็คเกจรากที่มีลักษณะเช่นนี้

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

นี่คือไฟล์ index.js

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

ตอนนี้สมมติว่าเรามี defaults.json อย่างนั้น

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

และ development.json อย่างนั้น

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

ถ้าคุณทำconfig = require('./config')ที่นี่คือสิ่งที่คุณจะได้รับ

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

ขอให้สังเกตว่าคุณได้รับค่าเริ่มต้นทั้งหมดยกเว้นที่กำหนดไว้ในไฟล์เฉพาะสภาพแวดล้อม ดังนั้นคุณสามารถจัดการลำดับชั้นการกำหนดค่า การใช้defaultsDeepทำให้แน่ใจว่าคุณสามารถมีค่าเริ่มต้นที่ซ้อนกันได้



0

ฉันลองวิธีแก้ปัญหาที่แนะนำบางอย่างที่นี่ แต่ไม่ได้ตอบโต้กับพวกเขาดังนั้นฉันจึงสร้างโมดูลของตัวเอง มันถูกเรียกว่าmikro-configและความแตกต่างที่สำคัญคือมันให้เกียรติอนุสัญญามากกว่าการกำหนดค่าดังนั้นคุณสามารถเพียงแค่ต้องใช้โมดูลและเริ่มใช้มัน

คุณเก็บการกำหนดค่าของคุณในไฟล์ js ธรรมดาหรือไฟล์ json จาก/configโฟลเดอร์ ก่อนอื่นให้โหลดdefault.jsไฟล์จากนั้นไฟล์อื่นทั้งหมดจาก/configไดเรกทอรีจากนั้นจะโหลดการกำหนดค่าเฉพาะสภาพแวดล้อมตาม$NODE_ENVตัวแปร

นอกจากนี้ยังอนุญาตให้แทนที่การกำหนดค่านี้สำหรับการพัฒนาในท้องถิ่นด้วยlocal.jsหรือเฉพาะสภาพแวดล้อม/config/env/$NODE_ENV.local.jsหรือสภาพแวดล้อมที่เฉพาะเจาะจง

คุณสามารถดูได้ที่นี่:

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

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


0

นานมาแล้วที่ฉันเคยใช้วิธีการที่กล่าวถึงในการแก้ปัญหาที่นี่ มีข้อกังวลเกี่ยวกับความปลอดภัยของความลับในข้อความที่ชัดเจน คุณสามารถใช้แพ็คเกจอื่นที่อยู่ด้านบนconfigเพื่อให้บิตความปลอดภัยได้รับการดูแล

ลองดูสิ: https://www.attosol.com/secure-application-secrets-using-masterkey-in-azure-key-vault/


ทำไมฉันถึงต้องสมัครเป็นสมาชิก Azure เพื่อชำระค่าบริการนี้ ทำไมไม่ใช้ตู้เซฟนิรภัย? อีกสิ่งหนึ่ง: ฉันคิดว่าจะไม่มีใครโพสต์ไฟล์กำหนดค่าด้วยข้อมูลรับรองข้อความที่ชัดเจนบนที่เก็บข้อมูลต้นทาง ใช้ตัวแปรสภาพแวดล้อมหรือใส่ข้อมูลลับของคุณลงในไฟล์ที่มีสิทธิ์อ่านอย่างเดียว
Yasser Sinjab

หากคุณสามารถอ่านได้จากที่ตั้งของบุคคลที่สามและถอดรหัสและให้บริการของคุณใช้ข้อมูลลับสุดยอดมันจะเป็นไปได้ที่แฮ็กเกอร์จะทำสิ่งเดียวกันหากพวกเขาเข้าถึงคอมพิวเตอร์ของคุณ มันใช้งานได้มากกว่า (ใช้เวลานานกว่า) แต่ในที่สุดมันก็ไม่ได้ป้องกันคุณ หากเซิร์ฟเวอร์ของคุณถูกเจาะลองนึกภาพว่าทุกสิ่งที่คุณมีอยู่ตอนนี้กลายเป็นสาธารณะ
Alexis Wilke
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.