Node.js thiết lập cấu hình môi trường cụ thể để sử dụng với everyauth


117

Tôi đang sử dụng node.js + express.js + everyauth.js. Tôi đã chuyển tất cả logic everyauth của mình vào một tệp mô-đun

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

bên trong này, tôi tải tệp cấu hình oAuth của mình bằng các tổ hợp khóa / bí mật:

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

Các mã này khác nhau đối với các môi trường khác nhau - phát triển / dàn dựng / sản xuất vì các lệnh gọi lại là các url khác nhau.

Qu. Làm cách nào để đặt chúng trong cấu hình môi trường để lọc qua tất cả các mô-đun hoặc tôi có thể chuyển trực tiếp đường dẫn vào mô-đun không?

Đặt trong env:

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

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

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

Đi vào

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

? hy vọng điều đó có ý nghĩa


Đã tìm thấy một giải pháp sử dụng một số ý tưởng từ bên dưới, bằng cách đặt module = function chứ không phải một đối tượng, tôi có thể đánh giá process.env.NODE_ENV và trả về đối tượng chính xác cho môi trường. Một chút lộn xộn nhưng hiệu quả.
andy t

Pardon sự không biết xấu hổ tự quảng bá, nhưng tôi đã viết một module cho Node.js rằng sẽ thực hiện điều này thông qua tập tin riêng biệt và một chuyển đổi dòng lệnh: nút-configure
Randolpho

Câu trả lời:


192

Giải pháp của tôi,

tải ứng dụng bằng cách sử dụng

NODE_ENV=production node app.js

Sau đó, thiết lập config.jsdưới dạng một hàm thay vì một đối tượng

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

        case 'production':
            return {prod settings};

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

Sau đó, theo giải pháp Jans tải tệp và tạo một phiên bản mới mà chúng tôi có thể chuyển vào một giá trị nếu cần, trong trường hợp process.env.NODE_ENVnày là toàn cục nên không cần thiết.

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

Sau đó, chúng tôi có thể truy cập các thuộc tính đối tượng cấu hình chính xác như trước

conf.twitter.consumerKey

2
Tại sao bạn sử dụng mới ở đây?
bluehallu

5
Tôi thứ hai @bluehallu. Có newcần thiết không?
Sung Cho

2
tương đương trong Windows sẽ SET NODE_ENV = phát triển
mujaffars

3
Thay vì làm new. Tôi làm theo sau config.js....Config = function(){...}; module.exports = Config()
Atu

Nếu tôi có 50 máy chủ web trong trường hợp này nó sẽ là khó khăn để tiếp tục mỗi máy chủ tự bắt đầu kịch bản
Rajesh

60

Bạn cũng có thể có tệp JSON với NODE_ENV là cấp cao nhất. IMO, đây là cách tốt hơn để thể hiện cài đặt cấu hình (trái ngược với việc sử dụng tập lệnh trả về cài đặt).

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

Ví dụ cho env.json:

{
    "development": {
        "MONGO_URI": "mongodb://localhost/test",
        "MONGO_OPTIONS": { "db": { "safe": true } }
    },
    "production": {
        "MONGO_URI": "mongodb://localhost/production",
        "MONGO_OPTIONS": { "db": { "safe": true } }
    }
}

Xin chào, bạn có thể vui lòng giải thích lý do tại sao bạn cho rằng đây là cách tốt hơn để thể hiện cài đặt cấu hình (thay vì sử dụng tập lệnh trả về cài đặt). ?
Venkat Kotra

14
Tôi đoán nó không tạo ra quá nhiều khác biệt. Về mặt tinh thần, khi tôi nhìn thấy JSON, tôi nghĩ là 'dữ liệu tĩnh' so với khi tôi nhìn thấy một tệp JS, tôi nghĩ rằng có một số logic bên trong nó. Ngoài ra, một lợi ích khác của việc sử dụng kiểu .json là các ngôn ngữ khác có thể nhập cùng một tệp.
mattwad

1
Cấu hình @VenkatKotra thường được coi là tĩnh và do đó, được thể hiện một cách khai báo tốt nhất với những thứ như json, yaml, ini, v.v. Được thực hiện theo thứ bậc, với một tập lệnh tạo ra trạng thái đó, kiểu ngụ ý có điều gì đó động đang xảy ra, điều này sẽ rất tệ.
tối đa

9
Lưu ý rằng phương pháp này tiết lộ thông tin xác thực trong kiểm soát nguồn.
Pier-Luc Gendreau

tôi có thể tạo url khác biệt cho dàn dựng và sản xuất không?
Alex

34

Một giải pháp rất hữu ích là sử dụng mô-đun cấu hình .

sau khi cài đặt mô-đun:

$ npm install config

Bạn có thể tạo tệp cấu hình default.json . (bạn có thể sử dụng đối tượng JSON hoặc JS bằng phần mở rộng .json5)

Ví dụ

$ vi config/default.json

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

Cấu hình mặc định này có thể được ghi đè bởi tệp cấu hình môi trường hoặc tệp cấu hình cục bộ cho môi trường phát triển cục bộ:

production.json có thể là:

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

development.json có thể là:

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

Trong PC cục bộ, bạn có thể có local.json ghi đè tất cả môi trường hoặc bạn có thể có cấu hình cục bộ cụ thể là local-production.json hoặc local-development.json .

Danh sách đầy đủ của thứ tự tải .

Bên trong ứng dụng của bạn

Trong ứng dụng của mình, bạn chỉ cần yêu cầu cấu hình và thuộc tính cần thiết.

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

Tải ứng dụng

tải ứng dụng bằng:

NODE_ENV=production node app.js

hoặc thiết lập môi trường chính xác với vĩnh viễn hoặc pm2

Mãi mãi:

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

PM2 (qua shell):

export NODE_ENV=staging
pm2 start app.js

PM2 (qua .json):

process.json

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

Và sau đó

$ pm2 start process.json --env production

Giải pháp này rất rõ ràng và nó giúp dễ dàng thiết lập các tệp cấu hình khác nhau cho môi trường Sản xuất / Dàn dựng / Phát triển và cả cài đặt cục bộ.


npm cài đặt cấu hình - lưu, nó không tốt hơn?
stackdave

14

Tóm lại

Kiểu thiết lập này rất đơn giản và thanh lịch:

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

Để chạy ở chế độ sản xuất: $ NODE_ENV=production node app.js


Chi tiết

Giải pháp này là từ: http://himanshu.gilani.info/blog/2012/09/26/bootstraping-a-node-dot-js-app-for-dev-slash-prod-enosystem/ , hãy kiểm tra để biết chi tiết hơn.


5

Cách chúng tôi thực hiện việc này là truyền một đối số vào khi khởi động ứng dụng với môi trường. Ví dụ:

node app.js -c dev

Trong app.js sau đó chúng tôi tải dev.jsdưới dạng tệp cấu hình của chúng tôi. Bạn có thể phân tích cú pháp các tùy chọn này bằng optparse-js .

Bây giờ bạn có một số mô-đun cốt lõi phụ thuộc vào tệp cấu hình này. Khi bạn viết chúng như vậy:

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

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

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

Và bạn có thể gọi nó app.jsnhư sau:

var Workspace = require("workspace");
this.workspace = new Workspace(config);

Tôi thà giữ tất cả các logic bên trong app.js app.configure('developmentmã, nhưng sẽ có một cái nhìn để xem nếu tôi có thể sử dụng giải pháp này với điều đó
andy t

Cập nhật câu trả lời này: Architect là một khung quản lý phụ thuộc giải quyết vấn đề này theo cách tốt hơn.
Jan Jongboom

5

Một cách đơn giản là sử dụng .envtệp để ghi đè cục bộ cài đặt sản xuất. Không cần chuyển mạch dòng lệnh. Không cần tất cả những dấu phẩy và dấu ngoặc trong một config.jsontệp. Xem câu trả lời của tôi tại đây

Ví dụ: trên máy của tôi, .envtệp này là:

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

Cục bộ của tôi .envghi đè bất kỳ biến môi trường nào. Nhưng trên máy chủ dàn dựng hoặc máy chủ sản xuất (có thể chúng nằm trên heroku.com), các biến môi trường được thiết lập trước cho giai đoạn NODE_ENV=stagehoặc sản xuất NODE_ENV=prod.


4

đặt biến môi trường trong máy chủ triển khai (ví dụ: như NODE_ENV = production). Bạn có thể truy cập biến môi trường của mình thông qua process.env.NODE_ENV. Tìm tệp cấu hình sau cho cài đặt chung

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 : 'some@user.com',
    },
    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;

cơ sở chứa cấu hình chung cho tất cả các môi trường.

sau đó nhập vào các mô-đun khác như

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

Mã hóa vui vẻ ...


3

Làm thế nào về việc thực hiện điều này theo cách thanh lịch hơn nhiều với mô-đun nodejs-config .

Mô-đun này có thể thiết lập môi trường cấu hình dựa trên tên máy tính của bạn. Sau đó, khi bạn yêu cầu một cấu hình, bạn sẽ nhận được giá trị môi trường cụ thể.

Ví dụ, giả sử bạn có hai máy phát triển có tên pc1 và pc2 và một máy sản xuất có tên pc3. Khi bạn yêu cầu các giá trị cấu hình trong mã của bạn trong pc1 hoặc pc2, bạn phải có được cấu hình môi trường "phát triển" và trong pc3 bạn phải nhận được cấu hình môi trường "sản xuất". Điều này có thể đạt được như thế này:

  1. Tạo tệp cấu hình cơ sở trong thư mục cấu hình, giả sử "app.json" và thêm các cấu hình cần thiết vào đó.
  2. Bây giờ chỉ cần tạo các thư mục trong thư mục cấu hình khớp với tên môi trường của bạn, trong trường hợp này là "phát triển" và "sản xuất".
  3. Tiếp theo, tạo tệp cấu hình bạn muốn ghi đè và chỉ định các tùy chọn cho từng môi trường tại thư mục môi trường (Lưu ý rằng bạn không phải chỉ định mọi tùy chọn có trong tệp cấu hình cơ sở, mà chỉ các tùy chọn bạn muốn ghi đè. các tệp cấu hình môi trường sẽ "xếp tầng" trên các tệp cơ sở.).

Bây giờ tạo phiên bản cấu hình mới với cú pháp sau.

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

   }
);

Bây giờ bạn có thể nhận bất kỳ giá trị cấu hình nào mà không cần lo lắng về môi trường như thế này:

config.get('app').configurationKey;

0

Câu trả lời này không phải là một cái gì đó mới. Nó tương tự như những gì @andy_t đã đề cập. Nhưng tôi sử dụng mô hình dưới đây vì hai lý do.

  1. Triển khai sạch sẽ không có phụ thuộc npm bên ngoài

  2. Hợp nhất cài đặt cấu hình mặc định với cài đặt dựa trên môi trường.

Triển khai 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] }

Tôi thường sử dụng bản ghi trong dự án nút của mình. Dưới đây là bản sao thực hiện triển khai thực tế của tôi.

Triển khai bảng chữ

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)
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.