nodejs 配置文件處理方案

前言

通常來講:一個好的項目配置應該知足如下條件:javascript

  1. 依賴環境:配置根據具體運行環境從相應的文件讀取
  2. 代碼分離:配置項不只能夠從配置文件讀取, 也能夠從環境變量讀取,使得安全隱祕的配置項與代碼分離
  3. 易於使用:配置項應該是分層配置的,有助於查找條目和維護龐大的配置文件的,應該是容易組織和容易獲取的,好比json結構

在多人開發 nodejs 項目的時候,沒有規劃好配置方案,配置文件的問題就很容易暴露出來。java

痛點

在開發 nodejs 的工程中,遇到過三個痛點node

  1. 部署環境不一樣: 開發、測試、生產環境的不一樣,致使配置的不一樣
  2. 開發環境不一樣: 開發者的開發環境配置不一樣,會存在同一個配置文件配置項不一樣,同一文件不一樣內容提交,容易引發 git 衝突,影響 git 提交更新
  3. 安全地配置: 一些配置不該該明文保存在項目代碼裏面,好比數據庫密碼

解決方案

部署環境不一樣

對於部署環境不一樣,相對容易解決,創建相應環境的配置文件,好比:git

  1. 開發環境配置:developmentConfig.js
  2. 測試環境配置:testConfig.js
  3. 生產環境配置:productionConfig.js

再建一個config.js配置文件做爲入口獲取配置,以下:數據庫

module.exports = require(`./${process.env.NODE_ENV}Config.js`)

引用配置的時候,只要引用 config.js 便可。
運行命令以下:npm

NODE_ENV=development node index.js

開發環境不一樣

對於開發環境不一樣,致使每一個人的developmentConfig.js不一樣,這個不能要求別人的配置和你的同樣,這樣項目就太硬了。
咱們能夠把developmentConfig.js添加到.gitignore,從而從項目分離出來,再在readme.md說明如何配置developmentConfig.js
最好是創建一個developmentConfig.example.js,並在文檔說明覆製成developmentConfig.js後修改配置項符合本身的開發配置。json

安全地配置

對於項目一些安全性要求高的配置項,咱們應該從配置文件脫離出來,只能在當前的運行進程能夠獲取, 配置文件的配置項再讀取進程的配置項值,好比數據庫密碼, 通常作法以下:
productionConfig.jsapi

module.exports = {
    database: {
        user: process.env.user || 'root',
        password: process.env.password || 'yfwzx2019'
    }
}

而更隱祕的辦法是,你根本不知道我用環境變量覆蓋了配置項值,好比:安全

productionConfig.jsapp

module.exports = {
    database: {
        user: 'root',
        password: 'yfwzx2019'
    }
}

通常人拿到了這個配置,就會覺得數據庫的帳號密碼就是rootyfwzx2019,其實最後會被環境變量的值覆蓋,運行以下:

node index.js --database.user=combine --database.password=tencent2019

固然,是要作了一些處理才能夠這樣配置。

實操

方案有了,咱們先來介紹如下 nodejs 的配置模塊 rc模塊

rc 模塊

使用rc模塊須要定義一個appname,選擇rc模塊是由於它會盡量多的從appname命名相關的地方讀取配置。
使用也很簡單,先實例一個 rc 配置:

var conf = require('rc')(appname, defaultConfigObject)

而後它會從下面列表合併配置,優先級按順序合併:

  1. 命令行參數:--user=root 或者對象形式賦值 --database.user=root
  2. 環境變量: 環境變量前綴爲${appname}_的變量 appname_user=root 對象形式 appname_database__user=root
  3. 指定文件: node index.js --config file
  4. 默認配置文件: 從 ./ ../ ../../ ../../../等目錄查找.${appname}rc文件
  5. $HOME/.${appname}rc
  6. $HOME/.${appname}/config
  7. $HOME/.config/${appname}
  8. $HOME/.config/${appname}/config
  9. /etc/${appname}rc
  10. /etc/${appname}/config

作了個 demo, 直觀一點

var conf = require('rc')('development', {
  port: 3000,
})
console.log(JSON.stringify(conf))

// 一、直接運行
// node index.js
// { port: 3000, _: [] }

// 二、加上命令行參數
// node index.js --port=4000 --database.user=root
// { port: 4000, _: [], database: { user: 'root' } }

// 三、加上環境變量
// development_port=5000 development_database__password=yfwzx2019 node index.js 
// {"port":"5000","database":{"password":"yfwzx2019"},"_":[]}

// 四、指定配置文件:根目錄建一個配置文件 config.json, 內容以下
// {
//   "port": "6000"
// }
// node index.js --config=config.json
// {"port":"6000","_":[],"config":"config.json","configs":["config.json"]}

// 五、默認讀取 ${appname}rc 文件:根目錄見一個配置文件 .developmentrc 內容以下:
// {
//   "port": 7000  
// }
// node index.js
// {"port":7000,"_":[],"configs":[".developmentrc"],"config":".developmentrc"}

// 六、 5 和4 一塊兒運行
// node index.js --config=config.json
// {"port":"6000","_":[],"config":"config.json","configs":[".developmentrc","config.json"]}

具體操做

看了 rc 模塊,能夠知足咱們的需求,咱們能夠配置公共的配置項,也能夠隱祕的覆蓋咱們的配置項。

  1. 建立配置文件目錄,添加配置文件
├── config
│   ├── .developmentrc.example
│   ├── .productionrc
│   ├── .testrc
│   └── index.js

其中 .developmentrc.example 是開發環境的例子,而後開發人員參考建 .developmentrc 文件, index.js 是配置入口文件,內容以下:

let rc = require('rc')

// 由於 rc 是從 process.cwd() 向上查找 .appnamerc 文件的,咱們在根目錄 config 文件夾裏面的是找不到的,要改變工做路徑到當前,再改回去
var originCwd = process.cwd()
process.chdir(__dirname)
var conf = rc(process.env.NODE_ENV || 'production', {
  // 默認的共同配置
  origin: 'default',
  baseUrl: 'http://google.com/api',
  enableProxy: true,
  port: 3000,
  database: {
    user: 'root',
    password: 'yfwzx2019'
  }
})

process.chdir(originCwd)

module.exports = conf
  1. 關於部署環境的不一樣,獲取配置經過設置環境變量NODE_ENV來適配
  2. 關於開發環境的不一樣,在.gitignore添加config/.developmentrc,項目代碼去掉開發環境配置.developmentrc,開發人員根據.developmentrc.example建直接的開發配置.developmentrc
  3. 關於安全地配置,經過添加環境變量覆蓋默認值,能夠安全隱祕地覆蓋配置項,好比:
NODE_ENV=production node index.js --database.password=tencent2019

謝謝你們

相關文章
相關標籤/搜索