Làm cách nào để lưu trữ tệp cài đặt / cấu hình triển khai Node.js?


640

Tôi đã làm việc trên một vài ứng dụng Node và tôi đang tìm kiếm một mô hình tốt về lưu trữ các cài đặt liên quan đến triển khai. Trong thế giới Django (nơi tôi đến), thực tế phổ biến là có một settings.pytệp chứa các cài đặt tiêu chuẩn (múi giờ, v.v.), sau đó là một local_settings.pycài đặt cụ thể để triển khai, tức là. cơ sở dữ liệu nào để nói chuyện, ổ cắm memcache nào, địa chỉ e-mail cho quản trị viên, v.v.

Tôi đã tìm kiếm các mẫu tương tự cho Node. Chỉ cần một tệp cấu hình là tốt, vì vậy nó không phải bị kẹt với mọi thứ khác app.js, nhưng tôi thấy điều quan trọng là phải có cách cấu hình máy chủ cụ thể trong một tệp không nằm trong kiểm soát nguồn. Cùng một ứng dụng có thể được triển khai trên các máy chủ khác nhau với các cài đặt cực kỳ khác nhau và phải xử lý các xung đột hợp nhất và tất cả đó không phải là ý tưởng thú vị của tôi.

Vì vậy, có một số loại khung / công cụ cho việc này, hoặc mọi người chỉ tự hack một cái gì đó với nhau?


tôi thực sự thích cách cấu hình được thực hiện trong mean.js . về cơ bản, họ lưu trữ cấu hình liên quan của ứng dụng trong một loại mô-đun riêng biệt, dựa trên các cài đặt khác nhau cho mỗi môi trường ứng dụng (để sản xuất, phát triển, thử nghiệm) và chuyển các chi tiết cụ thể thông qua các biến môi trường ứng dụng, như bí mật, v.v.
Hinrich

Câu trả lời:


765

Tôi sử dụng một package.jsoncho các gói của tôi và một config.jscho cấu hình của tôi, trông giống như:

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;

Tôi tải cấu hình từ dự án của tôi:

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

và sau đó tôi có thể truy cập vào những thứ của mình từ config.db_host, config.db_portv.v ... Điều này cho phép tôi sử dụng các tham số được mã hóa cứng hoặc các tham số được lưu trữ trong các biến môi trường nếu tôi không muốn lưu trữ mật khẩu trong kiểm soát nguồn.

Tôi cũng tạo một package.jsonvà chèn một phần phụ thuộc:

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

Khi tôi sao chép dự án vào máy cục bộ của mình, tôi chạy npm installđể cài đặt các gói. Thêm thông tin về điều đó ở đây .

Dự án được lưu trữ trong GitHub, với điều khiển từ xa được thêm vào máy chủ sản xuất của tôi.


32
Điều gì xảy ra khi bạn có các cài đặt cấu hình khác nhau cho dev so với prod?
chovy

4
Tôi không có nhưng đây là một cách để làm điều đó .. với mỗi env, hãy đặt tên env trong một biến ENV. Sau đó, trong tệp này, nó chỉ là javascript .. sử dụng một trường hợp hoặc câu lệnh if để tải có chọn lọc các biến thích hợp. Bạn thậm chí có thể tạo một tập tin con cấu hình riêng cho từng env và trong câu lệnh if, tải lại tập tin con ở đây vào một cấu hình con var và xuất var cấu hình con đó sang cấu hình chính .. Về cơ bản, tôi đang cố gắng nói rằng đó chỉ là js, vì vậy bạn có thể sáng tạo
noli

4
quá trình gì.env? nó nằm ở đâu Và làm thế nào để thiết lập nó?
kiwi tức giận

12
Tôi đã suy nghĩ "wow .. tôi đã xem xét node.js trong vài giờ và ứng dụng của tôi đã hoạt động .. btw, có lẽ tôi sẽ chia sẻ đoạn mã ngẫu nhiên này mà tôi đã nghĩ ra"
noli

3
Bạn vẫn có thể sử dụng các biến môi trường để lưu trữ các từ đó chứ? Không phải đó là những gì dòng này dành cho: config.twitter.password = process.env.TWITTER_PASSWORD || 'mật khẩu';
DMart

244

Bạn có thể yêu cầu các tệp JSON kể từ Node v0.5.x ( tham khảo câu trả lời này )

config.json:

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

app.js:

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

40
Không quá ấn tượng với tính năng đó. Bạn có thể yêu cầu ("./ config.js") và bạn có khả năng thêm nhận xét vào các tệp cấu hình mà tôi cho là rất quan trọng và các chuông và còi khác. Nếu cấu hình của bạn chỉ là thuộc tính và không có mã, bạn không mất gì khi yêu cầu (config.js) với bạn JSON có tiền tố là
export.config

3
@teknopaul bạn đúng nhưng đã từng có một cuộc thảo luận lớn về 'tính đúng đắn' / khả năng sử dụng các hệ thống tạo khuôn câm so với thông minh nói với tôi: (1) bạn thường muốn có một ngôn ngữ khai báo / câm để tạo khuôn mẫu / tùy chọn (2) đó là một ý tưởng tồi để tái cấu trúc một "gần như PL" để thực hiện templating (hoặc cấu hình) để sử dụng lại PL thực sự hiện tại của bạn với các hành vi đã biết. cho đến nay +1 để tái chế JS để thực hiện cài đặt người dùng; -1 vì không đi theo cách tiếp cận khai báo. chúng tôi đã thấy một số công cụ cấu hình khá phức tạp được thực hiện theo cách khai báo; ruột của tôi nói với tôi đây là con đường để đi.
chảy

1
Không có thông tin về các đối tượng từ các tệp json trong VScode (cuối năm 2017). Intellisense làm việc đầy đủ cho các đối tượng từ module.exports.
Romain Vincent

199

Rất lâu sau, tôi đã tìm thấy một mô-đun Node.js khá tốt để quản lý cấu hình: nconf .

Một ví dụ đơn giản:

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

Nó cũng hỗ trợ lưu trữ cài đặt trong Redis , viết các tệp cấu hình và có API khá chắc chắn và cũng được hỗ trợ bởi một trong những cửa hàng Node.js được tôn trọng hơn, Nodejitsu , như một phần của sáng kiến ​​khung Flatiron , do đó, nó phải là tương lai khá bằng chứng.

Kiểm tra nconf tại Github .


2
Có thể một câu hỏi ngớ ngẩn nhưng tôi chưa thấy một lời giải thích rõ ràng: Tôi đặt các biến môi trường nút ở đâu? Tôi đã sử dụng nconf nhưng không rõ tôi sẽ đặt biến môi trường ở đâu. Có phải trong nginx / apache? Có phải là một tập tin cấu hình khác?
Dân sự

91
Tôi không nghĩ sử dụng tệp .json vì cấu hình là một ý tưởng hay, vì các bình luận không được phép.
Frank Xu

11
Điều này có vẻ tuyệt vời. Tôi nghĩ bạn sẽ ngạc nhiên rất nhiều Unixhead nếu tệp cấu hình ghi đè các tùy chọn dòng lệnh và biến môi trường. Chúng ta đã quen với thứ tự ưu tiên tăng dần sau: tệp cấu hình, biến môi trường, tùy chọn dòng lệnh.
sheldonh

2
@sheldonh Đợi cho đến khi bạn phát hiện ra rằng các tùy chọn boolean luôn được đặt trên argv, do đó phá vỡ quyền ưu tiên ...: /
Daniel C. Sobral

@ DanielC.Sobral Thật xấu hổ. Ồ, và LTNS! :-)
sheldonh

94

Giải pháp của tôi khá đơn giản:

Tải cấu hình môi trường trong ./config/index.js

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

module.exports = cfg;

Xác định một số giá trị mặc định trong ./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';

Ghi đè mặc định trong ./config/config.test.js

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

config.env = 'test';
config.hostname = 'test.example';
config.mongo.db = 'example_test';

module.exports = config;

Sử dụng nó trong ./models/user.js:

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

Chạy ứng dụng của bạn trong môi trường thử nghiệm:

NODE_ENV=test node ./app.js

2
Tôi thích cái này Như những người khác đã đề cập, JSON không phải là một cấu trúc lưu trữ ưa thích và việc tạo lớp với toàn cầu này rất đơn giản và hiệu quả
Sebastian J.

Lý do duy nhất tôi thích điều này hơn nconf là vì nó cho phép định dạng .js cho các tệp config (dev, test và prod). cho phép chúng tôi ghi lại từng tùy chọn cấu hình mà định dạng JSON không thể thực hiện được.
Kunal Kapadia

BTW, NODE_ENVmặc định là 'phát triển'. Thay vào đó, bạn nên kiểm tra 'sản xuất'.
Kevin Scos

5
Tôi không kiểm tra sự phát triển. Tôi đang mặc định nó. Không chắc chắn tại sao tôi sẽ mặc định sản xuất.
chovy

39

Bạn cũng có thể tìm đến dotenv theo nguyên lý của ứng dụng mười hai yếu tố .

Tôi đã từng sử dụng nút-config, nhưng đã tạo dotenv vì lý do đó. Nó hoàn toàn lấy cảm hứng từ thư viện dotenv của ruby.

Cách sử dụng khá dễ dàng:

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

Sau đó, bạn chỉ cần tạo tệp .env và đặt cài đặt của mình vào đó như sau:

S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE
OTHER_SECRET_STUFF=my_cats_middle_name

Đó là dotenv cho nodejs.


2
Hoặc chỉ sử dụng foreman run node xx.jsđiều này sẽ tự động đọc trong tệp .env của bạn.
Simon

1
Tôi cũng sẽ sử dụng phương pháp này cho sản xuất chứ?
Lamour

1
@lamar không, bạn đặt chúng trong các biến env trên máy chủ thực tế. Đó là mỗi lần bạn triển khai chúng ở đó nhưng không có trong mã nguồn.
sidonaldson

@Lamar vâng, bạn thực sự có thể, như một sự thay thế di động hơn để đặt các biến env trên máy chủ. Điểm quan trọng là không bao gồm .envtệp trong quá trình triển khai hoặc kiểm soát phiên bản của bạn.
Josh Noe

31

Các bạn có đang sử dụng npm để bắt đầu tập lệnh của mình không (env, v.v.)?

Nếu bạn sử dụng .envtập tin, bạn có thể đưa chúng vàopackage.json và sử dụng npm để nguồn / khởi động chúng.

Thí dụ:

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

sau đó chạy các kịch bản npm:

$ npm start-dev

Nó được mô tả ở đây https://gist.github.com/ericelliott/4152984 Tất cả tín dụng cho Eric Elliot


2
Bạn có thể giải thích "nguồn" là gì? Tôi nhận đượcsource : not found
JohnnyBizzle

@JohnnyBizzle source(hoặc đơn giản, .) là một lệnh tích hợp trong shell Unix (Bash, v.v.) để đọc và thực thi các lệnh từ tệp đã cho, trong shell hiện tại . Đó là, các lệnh không được thực thi trong shell phụ. Tác động của điều đó trong ví dụ này là các biến môi trường được xác định trong prod.envđược thêm vào shell hiện tại và do đó, được truyền cho bất kỳ tiến trình con nào được sinh ra bởi shell này. Bạn dường như đang sử dụng Windows CMD. Xem câu hỏi này để biết thêm chi tiết.
Utku

Đáng chú ý - ứng dụng 12 yếu tố khuyên bạn không nên tạo dev.envprod.env, nhưng có một .envtệp duy nhất cho mỗi lần triển khai.
Iiridayn

24

Bạn cũng có thể tìm đến nút-config để tải tệp cấu hình tùy thuộc vào biến $ HOST$ NODE_ENV (hơi giống với RoR): tài liệu .

Điều này có thể khá hữu ích cho các thiết lập triển khai khác nhau ( development, testhoặc production).


22

Chỉ cần làm một cách đơn giản settings.jsvới exports:

exports.my_password = 'value'

Sau đó, trong kịch bản của bạn, hãy thực hiện require:

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

Tất cả các cài đặt của bạn bây giờ sẽ có sẵn thông qua settingsbiến:

settings.my_password // 'value'

@backdesk tất nhiên bạn có thể thiết lập một hệ thống lưu trữ bí mật sẽ mã hóa bí mật và hạn chế quyền truy cập bằng ip, một số mã thông báo, v.v. Nhưng cuối cùng, tất cả chỉ cần đọc một số tệp từ đĩa, được mã hóa hoặc không phải.
Vanuan

@backdesk Không có vấn đề với ví dụ. Chỉ là: một ví dụ để giải thích một cái gì đó cụ thể.
Emilio Grisolía

14

Tôi sẽ ném mũ vào vòng vì ở đây không có câu trả lời nào giải quyết được tất cả các thành phần quan trọng mà hầu như bất kỳ hệ thống nào cũng cần. Cân nhắc:

  • Cấu hình công khai (có thể được nhìn thấy bởi frontend) so với cấu hình riêng tư (anh chàng mograbi đã hiểu điều này đúng). Và đảm bảo những điều này được giữ riêng biệt.
  • Bí mật như chìa khóa
  • Mặc định so với ghi đè dành riêng cho môi trường
  • Gói Frontend

Đây là cách tôi thực hiện cấu hình của mình:

  • config.default.private.js - Trong kiểm soát phiên bản, đây là các tùy chọn cấu hình mặc định chỉ có thể nhìn thấy bởi phụ trợ của bạn.
  • config.default.public.js- Trong kiểm soát phiên bản, đây là các tùy chọn cấu hình mặc định có thể được nhìn thấy bởi phụ trợ frontend
  • config.dev.private.js - Nếu bạn cần mặc định riêng tư khác nhau cho dev.
  • config.dev.public.js - Nếu bạn cần mặc định công khai khác nhau cho dev.
  • config.private.js - Không có trong kiểm soát phiên bản, đây là các tùy chọn dành riêng cho môi trường ghi đè config.default.private.js
  • config.public.js - Không có trong kiểm soát phiên bản, đây là các tùy chọn dành riêng cho môi trường ghi đè config.default.public.js
  • keys/- Một thư mục trong đó mỗi tệp lưu trữ một bí mật khác nhau. Điều này cũng không thuộc kiểm soát phiên bản (các phím không bao giờ được kiểm soát phiên bản).

Tôi sử dụng các tệp javascript cũ để cấu hình để tôi có toàn bộ sức mạnh của ngôn ngữ javascript (bao gồm các nhận xét và khả năng thực hiện những việc như tải tệp cấu hình mặc định trong tệp dành riêng cho môi trường để chúng có thể bị ghi đè). Nếu bạn muốn sử dụng các biến môi trường, bạn có thể tải chúng bên trong các tệp cấu hình đó (tôi khuyên bạn không nên sử dụng env vars vì lý do tương tự tôi không khuyên bạn nên sử dụng tệp json - bạn không có khả năng của ngôn ngữ lập trình để xây dựng cấu hình của bạn).

Lý do mỗi khóa nằm trong một tệp riêng biệt là để sử dụng trình cài đặt. Điều này cho phép bạn có một trình cài đặt tạo khóa trên máy và lưu trữ chúng trong thư mục khóa. Nếu không có điều này, trình cài đặt của bạn có thể thất bại khi bạn tải tệp cấu hình không thể truy cập các khóa của mình. Bằng cách này, bạn có thể duyệt qua thư mục và tải bất kỳ tệp chính nào trong thư mục đó mà không phải lo lắng về những gì tồn tại và những gì không có trong bất kỳ phiên bản mã nào.

Vì bạn có thể có các khóa được tải trong cấu hình riêng tư của bạn, bạn chắc chắn không muốn tải cấu hình riêng tư của mình trong bất kỳ mã giao diện nào. Mặc dù có thể hoàn toàn lý tưởng hơn để tách hoàn toàn codebase của bạn khỏi phần phụ trợ của bạn, rất nhiều lần PITA là một rào cản đủ lớn để ngăn mọi người thực hiện nó, do đó, riêng tư so với cấu hình công khai. Nhưng có hai điều tôi làm để ngăn chặn cấu hình riêng tư được tải ở frontend:

  1. Tôi có một bài kiểm tra đơn vị đảm bảo các gói frontend của tôi không chứa một trong các khóa bí mật tôi có trong cấu hình riêng tư.
  2. Tôi có mã frontend của mình trong một thư mục khác với mã phụ trợ của tôi và tôi có hai tệp khác nhau có tên "config.js" - một tệp cho mỗi đầu. Đối với phụ trợ, config.js tải cấu hình riêng tư, đối với giao diện, nó tải cấu hình chung. Sau đó, bạn luôn chỉ yêu cầu ('config') và đừng lo lắng về việc nó đến từ đâu.

Một điều cuối cùng: cấu hình của bạn nên được tải vào trình duyệt thông qua một tệp hoàn toàn riêng biệt hơn bất kỳ mã giao diện nào khác của bạn. Nếu bạn bó mã frontend của mình, cấu hình công khai sẽ được xây dựng dưới dạng một gói hoàn toàn riêng biệt. Mặt khác, cấu hình của bạn không thực sự cấu hình nữa - nó chỉ là một phần của mã của bạn. Cấu hình cần phải có khả năng khác nhau trên các máy khác nhau.


13

Kết án là một tùy chọn khác có thêm một lược đồ để xác nhận. Giống như nconf, nó hỗ trợ tải các cài đặt từ bất kỳ tổ hợp biến môi trường, đối số, tệp và đối tượng json nào.

Ví dụ từ 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"
  }
});

Bắt đầu bài viết: Cấu hình thuần hóa với nút kết án


12

Bạn có thể sử dụng Konfig cho các tệp cấu hình cụ thể của môi trường. Nó tự động tải các tập tin cấu hình json hoặc yaml, nó có giá trị mặc định và các tính năng cấu hình động.

Một ví dụ từ 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"
    }
}

Trong giai đoạn phát triển:

> config.app.port
3000

Trong sản xuất, giả sử chúng ta bắt đầu ứng dụng với $ NODE_ENV=production PORT=4567 node app.js

> config.app.port
4567

Thêm chi tiết: https://github.com/vngrs/konfig


9

Tôi sẽ tạo một thư mục như cấu hình một tên tệp config.jsvà sau này tôi sẽ sử dụng tệp này bất cứ nơi nào được yêu cầu như dưới đây

Ví dụ về config.js

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

Sau đó, nếu tôi muốn sử dụng tập tin cấu hình này ở đâu đó

Trước tiên tôi sẽ nhập như sau

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

và tôi có thể truy cập các giá trị như dưới đây

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

Chỉ cần sử dụng npmmô-đun config(hơn 300000 lượt tải xuống)

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

Node-config tổ chức các cấu hình phân cấp cho việc triển khai ứng dụng của bạn.

Nó cho phép bạn xác định một tập hợp các tham số mặc định và mở rộng chúng cho các môi trường triển khai khác nhau (phát triển, qa, dàn dựng, sản xuất, v.v.).

$ 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

Tốt hơn là nên tách cấu hình 'phát triển''sản xuất' .

Tôi sử dụng cách sau: Đây là tệp config / index.js của tôi :

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

Để yêu cầu cấu hình sử dụng như sau:

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

Hơn bạn có thể sử dụng đối tượng cấu hình của bạn:

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

bạn cũng có thể sử dụng module.exports = config;ở cuối config/index.jstập tin
mapmalith

3

Tôi đến hơi muộn trong trò chơi, nhưng tôi không thể tìm thấy những gì tôi cần ở đây - hoặc bất cứ nơi nào khác - vì vậy tôi đã tự mình viết một cái gì đó.

Yêu cầu của tôi cho một cơ chế cấu hình là như sau:

  1. Hỗ trợ mặt trước. Điểm nào nếu front-end không thể sử dụng cấu hình?
  2. Hỗ trợ settings-overrides.js- trông giống nhau nhưng cho phép ghi đè cấu hình tại settings.js. Ý tưởng ở đây là sửa đổi cấu hình dễ dàng mà không thay đổi mã. Tôi thấy nó hữu ích cho saas.

Mặc dù tôi ít quan tâm đến các môi trường hỗ trợ - ý chí sẽ giải thích cách thêm nó dễ dàng vào giải pháp của tôi

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;

Giải trình

  • undefined có nghĩa là tài sản này là bắt buộc
  • null có nghĩa là nó là tùy chọn
  • meConf- hiện tại mã được nhắm mục tiêu đến một tập tin theo app. meConflà các tập tin ghi đè được nhắm mục tiêu conf/dev- bị bỏ qua bởi vcs của tôi.
  • publicConfiguration - sẽ hiển thị từ front-end và back-end.
  • privateConfiguration - sẽ chỉ hiển thị từ back-end.
  • sendPublicConfiguration- một tuyến đường sẽ hiển thị cấu hình công cộng và gán nó cho một biến toàn cục. Ví dụ, mã dưới đây sẽ hiển thị cấu hình công khai dưới dạng biến toàn cục myConf trong giao diện người dùng. Theo mặc định, nó sẽ sử dụng tên biến toàn cụcconf .

    app.get ("/ backend / conf", yêu cầu ("conf"). sendPublicConfiguration);

Logic của ghi đè

  • privateConfiguration được hợp nhất với publicConfiguration và sau đó là meConf.
  • publicConfiguration kiểm tra từng khóa nếu nó có ghi đè và sử dụng ghi đè đó. Bằng cách này, chúng tôi không tiết lộ bất cứ điều gì riêng tư.

Thêm hỗ trợ môi trường

Mặc dù tôi không thấy "hỗ trợ môi trường" hữu ích, nhưng có lẽ ai đó sẽ làm được.

Để thêm hỗ trợ môi trường, bạn cần thay đổi câu lệnh yêu cầu meConf thành một cái gì đó như thế này (mã giả)

if (môi trường == "sản xuất") {meConf = Yêu cầu ("../ conf / dev / meConf"). sản xuất; }

if (môi trường == "phát triển") {meConf = Yêu cầu ("../ conf / dev / meConf"). Development; }

Tương tự, bạn có thể có một tệp cho mỗi môi trường

 meConf.development.js
 meConf.production.js

và nhập đúng. Phần còn lại của logic vẫn giữ nguyên.


không quá rõ ràng mà undefinedthực sự có nghĩa là 'bắt buộc' và nullcó nghĩa là 'tùy chọn'. Vậy thùng màu vàng là cho nhựa và màu xanh cho giấy phế liệu? tốt, nhưng phải đọc hướng dẫn trước khi ném rác đó.
chảy

Bạn không phải sử dụng quy ước này. Tôi thấy nó hữu ích và tôi hướng dẫn nhóm của mình sử dụng nó, nhưng rõ ràng bạn có thể loại bỏ tính năng này.
anh chàng mograbi

3

một ví dụ thay thế tôi chỉ sử dụng vì tôi muốn linh hoạt hơn một tệp .json thông thường nhưng không muốn nó được trừu tượng hóa trong một thư viện đòi hỏi sự phụ thuộc là như thế này. Về cơ bản, xuất một hàm được gọi ngay lập tức trả về một đối tượng có giá trị tôi muốn đặt. Cung cấp rất nhiều tính linh hoạt.

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

Có một lời giải thích tốt hơn với ví dụ đầy đủ ở đây. Sử dụng tập tin cấu hình trong Node.js


3

Tôi biết đây là một bài viết thực sự cũ. Nhưng tôi muốn chia sẻ mô-đun của mình để cấu hình các biến môi trường, tôi nghĩ đó là giải pháp rất linh hoạt. Đây là mô-đun json-configure

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 

Sau đó, bạn có thể sử dụng process.env.NODE_ENVđể có được tất cả các biến cho môi trường của bạn.


2

Ngoài mô-đun nconf được đề cập trong câu trả lời nàycấu hình nút được đề cập trong câu trả lời này , còn có nút-iniparserIniReader , có vẻ là trình phân tích tệp cấu hình .ini đơn giản hơn.


không có cách nào để quay lại các tệp win-ini ... điều đó iniparsertự hào nhấn mạnh thực tế là họ biết cách phân tích các phần trong cấu hình ... vào năm 2013 ... nếu bạn cần lồng sâu hơn [foo/bar]? [foo\bar]? bar.baz=42? bar/baz=42? bar\baz=42? bar:baz=42? làm thế nào để bạn biết 42là một số? nó có thể là một văn bản gồm tất cả các chữ số! Giantoss XML, ném YAML, ném WIN.INI, ôm lấy JSON, lo lắng biến mất.
chảy



1

Dưới đây là một cách tiếp cận gọn gàng lấy cảm hứng từ bài viết này . Nó không yêu cầu bất kỳ gói bổ sung nào ngoại trừ gói lodash phổ biến . Hơn nữa, nó cho phép bạn quản lý các mặc định lồng nhau với các ghi đè cụ thể theo môi trường.

Đầu tiên, tạo một thư mục cấu hình trong đường dẫn gốc gói trông như thế này

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

đây là tệp index.js

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

Bây giờ hãy giả sử rằng chúng ta có một defaults.json như vậy

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

và Development.json cũng vậy

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

nếu bạn làm config = require('./config')ở đây là những gì bạn sẽ nhận được

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

Lưu ý rằng bạn nhận được tất cả các giá trị mặc định ngoại trừ các giá trị được xác định trong các tệp dành riêng cho môi trường. Vì vậy, bạn có thể quản lý một hệ thống phân cấp cấu hình. Sử dụng defaultsDeepđảm bảo rằng bạn thậm chí có thể có các mặc định lồng nhau.



0

Tôi đã thử một số giải pháp được đề xuất ở đây, nhưng không hài lòng với chúng, vì vậy tôi đã tạo ra mô-đun của riêng mình. Nó được gọi mikro-configvà sự khác biệt chính là nó tôn vinh quy ước về cấu hình, vì vậy bạn chỉ cần yêu cầu mô-đun và bắt đầu sử dụng nó.

Bạn lưu cấu hình của mình trong các tệp js hoặc json đơn giản từ /configthư mục. Đầu tiên, nó tải default.jstập tin, sau đó tất cả các tập tin khác từ /configthư mục, sau đó nó tải cấu hình cụ thể của môi trường dựa trên $NODE_ENVbiến.

Nó cũng cho phép ghi đè cấu hình này để phát triển cục bộ với local.jshoặc môi trường cụ thể/config/env/$NODE_ENV.local.js .

Bạn có thể nhìn vào nó ở đây:

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

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


0

Từ lâu, tôi đã từng sử dụng cách tiếp cận được đề cập trong giải pháp ở đây. Tuy nhiên, có một mối quan tâm về bảo mật của các bí mật trong văn bản rõ ràng. Bạn có thể sử dụng một gói khác ở trên cùng configđể các bit bảo mật được chăm sóc.

Hãy xem cái này: https://www.attosol.com/secure-application-secrets-USE-masterkey-in-azure-key-vault/


Tại sao tôi thậm chí nên đăng ký Azure để thanh toán dịch vụ này? Tại sao không sử dụng ansible-vault? Một điều nữa: Tôi nghĩ rằng không ai sẽ đăng một tập tin cấu hình với thông tin văn bản rõ ràng trên kho lưu trữ nguồn. Sử dụng các biến môi trường hoặc đặt dữ liệu bí mật của bạn vào một tệp với quyền chỉ đọc.
Yasser Sinjab

Nếu bạn có thể đọc nó từ một số vị trí của bên thứ 3 và giải mã nó và yêu cầu dịch vụ của bạn sử dụng dữ liệu tuyệt mật đó, thì hacker sẽ có thể làm điều tương tự nếu họ có quyền truy cập vào máy tính của bạn. Đó là công việc nhiều hơn (mất nhiều thời gian hơn) nhưng cuối cùng nó không bảo vệ bạn. Nếu máy chủ của bạn bị xâm nhập, hãy tưởng tượng rằng bất cứ thứ gì bạn có trên đó đều được công khai.
Alexis Wilke
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.