详解nodejs 配置文件处理方案


Posted in NodeJs onJanuary 02, 2019

前言

一般来说:一个好的项目配置应该满足以下条件:

  1. 依赖环境:配置根据具体运行环境从相应的文件读取
  2. 代码分离:配置项不仅可以从配置文件读取, 也可以从环境变量读取,使得安全隐秘的配置项与代码分离
  3. 易于使用:配置项应该是分层配置的,有助于查找条目和维护庞大的配置文件的,应该是容易组织和容易获取的,比如json结构

在多人开发 nodejs 项目的时候,没有规划好配置方案,配置文件的问题就很容易暴露出来。

痛点

在开发 nodejs 的工程中,遇到过三个痛点

  1. 部署环境不同: 开发、测试、生产环境的不同,导致配置的不同
  2. 开发环境不同: 开发者的开发环境配置不同,会存在同一个配置文件配置项不同,同一文件不同内容提交,容易引起 git 冲突,影响 git 提交更新
  3. 安全地配置: 一些配置不应该明文保存在项目代码里面,比如数据库密码

解决方案

部署环境不同

对于部署环境不同,相对容易解决,建立相应环境的配置文件,比如:

  1. 开发环境配置:developmentConfig.js
  2. 测试环境配置:testConfig.js
  3. 生产环境配置:productionConfig.js

再建一个config.js配置文件作为入口获取配置,如下:

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

引用配置的时候,只要引用 config.js 即可。

运行命令如下:

NODE_ENV=development node index.js

开发环境不同

对于开发环境不同,导致每个人的developmentConfig.js不同,这个不能要求别人的配置和你的一样,这样项目就太硬了。
我们可以把developmentConfig.js添加到.gitignore,从而从项目分离出来,再在readme.md说明如何配置developmentConfig.js。

最好是建立一个developmentConfig.example.js,并在文档说明复制成developmentConfig.js后修改配置项符合自己的开发配置。

安全地配置
对于项目一些安全性要求高的配置项,我们应该从配置文件脱离出来,只能在当前的运行进程可以获取, 配置文件的配置项再读取进程的配置项值,比如数据库密码, 一般做法如下:
productionConfig.js

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

而更隐秘的办法是,你根本不知道我用环境变量覆盖了配置项值,比如:

productionConfig.js

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

一般人拿到了这个配置,就会以为数据库的账号密码就是root、yfwzx2019,其实最后会被环境变量的值覆盖,运行如下:

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

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

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

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

// 4、指定配置文件:根目录建一个配置文件 config.json, 内容如下
// {
//  "port": "6000"
// }
// node index.js --config=config.json
// {"port":"6000","_":[],"config":"config.json","configs":["config.json"]}

// 5、默认读取 ${appname}rc 文件:根目录见一个配置文件 .developmentrc 内容如下:
// {
//  "port": 7000 
// }
// node index.js
// {"port":7000,"_":[],"configs":[".developmentrc"],"config":".developmentrc"}

// 6、 5 和4 一起运行
// node index.js --config=config.json
// {"port":"6000","_":[],"config":"config.json","configs":[".developmentrc","config.json"]}

具体操作

看了 rc 模块,可以满足我们的需求,我们可以配置公共的配置项,也可以隐秘的覆盖我们的配置项。

创建配置文件目录,添加配置文件

├── 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
  • 关于部署环境的不同,获取配置通过设置环境变量NODE_ENV来适配
  • 关于开发环境的不同,在.gitignore添加config/.developmentrc,项目代码去掉开发环境配置.developmentrc,开发人员根据.developmentrc.example建直接的开发配置.developmentrc
  • 关于安全地配置,通过添加环境变量覆盖默认值,可以安全隐秘地覆盖配置项,比如:
NODE_ENV=production node index.js --database.password=tencent2019

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

NodeJs 相关文章推荐
nodejs入门详解(多篇文章结合)
Mar 07 NodeJs
NodeJs中的非阻塞方法介绍
Jun 05 NodeJs
Nodejs中读取中文文件编码问题、发送邮件和定时任务实例
Jan 01 NodeJs
Nodejs进阶:基于express+multer的文件上传实例
Nov 21 NodeJs
用Nodejs搭建服务器访问html、css、JS等静态资源文件
Apr 28 NodeJs
Nodejs 和Session 原理及实战技巧小结
Aug 25 NodeJs
nodejs socket服务端和客户端简单通信功能
Sep 14 NodeJs
NodeJS爬虫实例之糗事百科
Dec 14 NodeJs
nodejs调取微信收货地址的方法
Dec 20 NodeJs
基于Koa(nodejs框架)对json文件进行增删改查的示例代码
Feb 02 NodeJs
nodejs 递归拷贝、读取目录下所有文件和目录
Jul 18 NodeJs
Nodejs + Websocket 指定发送及群聊的实现
Jan 09 NodeJs
nodejs基础之多进程实例详解
Dec 27 #NodeJs
nodejs基础之常用工具模块util用法分析
Dec 26 #NodeJs
nodejs基础之buffer缓冲区用法分析
Dec 26 #NodeJs
nodejs异步编程基础之回调函数用法分析
Dec 26 #NodeJs
Nodejs处理异常操作示例
Dec 25 #NodeJs
Nodejs模块的调用操作实例分析
Dec 25 #NodeJs
nodejs中方法和模块用法示例
Dec 24 #NodeJs
You might like
深入php socket的讲解与实例分析
2013/06/13 PHP
php中的PHP_EOL换行符详细解析
2013/10/26 PHP
PHPAnalysis中文分词类详解
2014/06/13 PHP
PHP实现把文本中的URL转换为链接的auolink()函数分享
2014/07/29 PHP
PHP children()函数讲解
2019/02/03 PHP
PHP实现数组向任意位置插入,删除,替换数据操作示例
2019/04/05 PHP
Javascript 遮罩层和加载效果代码
2013/08/01 Javascript
js实现iGoogleDivDrag模块拖动层拖动特效的方法
2015/03/04 Javascript
JS实现的简洁纵向滑动菜单(滑动门)效果
2015/10/19 Javascript
jQuery判断元素是否显示 是否隐藏的简单实现代码
2016/05/19 Javascript
jQuery插件Easyui设置datagrid的pageNumber导致两次请求问题的解决方法
2016/08/06 Javascript
String字符串截取的四种方式总结
2016/11/28 Javascript
BootStrap Datepicker 插件修改为默认中文的实现方法
2017/02/10 Javascript
详解Node全局变量global模块
2017/09/28 Javascript
JavaScript 正则命名分组【推荐】
2018/06/07 Javascript
JavaScript指定断点操作实例教程
2018/09/18 Javascript
使用VUE+iView+.Net Core上传图片的方法示例
2019/01/04 Javascript
详解从react转职到vue开发的项目准备
2019/01/14 Javascript
JavaScript 格式化数字、金额、千分位、保留几位小数、舍入舍去
2019/07/23 Javascript
Vue切换div显示隐藏,多选,单选代码解析
2020/07/14 Javascript
[01:01:23]完美世界DOTA2联赛PWL S2 Forest vs FTD.C 第一场 11.26
2020/11/30 DOTA
将Django使用的数据库从MySQL迁移到PostgreSQL的教程
2015/04/11 Python
深入解析Python中的lambda表达式的用法
2015/08/28 Python
解决python3在anaconda下安装caffe失败的问题
2017/06/15 Python
Python二叉树的镜像转换实现方法示例
2019/03/06 Python
python模拟斗地主发牌
2020/04/22 Python
英国独特的时尚和生活方式品牌:JOY
2018/03/17 全球购物
芭比波朗加拿大官方网站:Bobbi Brown Cosmetics CA
2020/11/05 全球购物
客户接待方案
2014/02/26 职场文书
环保建议书400字
2014/05/14 职场文书
五星级酒店前台接待岗位职责
2015/04/02 职场文书
通知函的格式
2015/04/27 职场文书
《一面五星红旗》教学反思
2016/02/23 职场文书
2019年健身俱乐部的创业计划书
2019/08/26 职场文书
Python字典的基础操作
2021/11/01 Python
一文搞懂MySQL索引页结构
2022/02/28 MySQL