详解nodejs 配置文件处理方案
前言
一般来说:一个好的项目配置应该满足以下条件:
- 依赖环境:配置根据具体运行环境从相应的文件读取
- 代码分离:配置项不仅可以从配置文件读取,也可以从环境变量读取,使得安全隐秘的配置项与代码分离
- 易于使用:配置项应该是分层配置的,有助于查找条目和维护庞大的配置文件的,应该是容易组织和容易获取的,比如json结构
在多人开发nodejs项目的时候,没有规划好配置方案,配置文件的问题就很容易暴露出来。
痛点
在开发nodejs的工程中,遇到过三个痛点
- 部署环境不同:开发、测试、生产环境的不同,导致配置的不同
- 开发环境不同:开发者的开发环境配置不同,会存在同一个配置文件配置项不同,同一文件不同内容提交,容易引起git冲突,影响git提交更新
- 安全地配置:一些配置不应该明文保存在项目代码里面,比如数据库密码
解决方案
部署环境不同
对于部署环境不同,相对容易解决,建立相应环境的配置文件,比如:
- 开发环境配置:developmentConfig.js
- 测试环境配置:testConfig.js
- 生产环境配置:productionConfig.js
再建一个config.js配置文件作为入口获取配置,如下:
module.exports=require(`./${process.env.NODE_ENV}Config.js`)
引用配置的时候,只要引用config.js即可。
运行命令如下:
NODE_ENV=developmentnodeindex.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,其实最后会被环境变量的值覆盖,运行如下:
nodeindex.js--database.user=combine--database.password=tencent2019
当然,是要做了一些处理才可以这样配置。
实操
方案有了,我们先来介绍以下nodejs的配置模块rc模块
rc模块
使用rc模块需要定义一个appname,选择rc模块是因为它会尽可能多的从appname命名相关的地方读取配置。
使用也很简单,先实例一个rc配置:
varconf=require('rc')(appname,defaultConfigObject)
然后它会从下面列表合并配置,优先级按顺序合并:
- 命令行参数:--user=root或者对象形式赋值--database.user=root
- 环境变量:环境变量前缀为${appname}_的变量appname_user=root对象形式appname_database__user=root
- 指定文件:nodeindex.js--configfile
- 默认配置文件:从./../../../../../../等目录查找.${appname}rc文件
- $HOME/.${appname}rc
- $HOME/.${appname}/config
- $HOME/.config/${appname}
- $HOME/.config/${appname}/config
- /etc/${appname}rc
- /etc/${appname}/config
做了个demo,直观一点
varconf=require('rc')('development',{ port:3000, }) console.log(JSON.stringify(conf)) //1、直接运行 //nodeindex.js //{port:3000,_:[]} //2、加上命令行参数 //nodeindex.js--port=4000--database.user=root //{port:4000,_:[],database:{user:'root'}} //3、加上环境变量 //development_port=5000development_database__password=yfwzx2019nodeindex.js //{"port":"5000","database":{"password":"yfwzx2019"},"_":[]} //4、指定配置文件:根目录建一个配置文件config.json,内容如下 //{ //"port":"6000" //} //nodeindex.js--config=config.json //{"port":"6000","_":[],"config":"config.json","configs":["config.json"]} //5、默认读取${appname}rc文件:根目录见一个配置文件.developmentrc内容如下: //{ //"port":7000 //} //nodeindex.js //{"port":7000,"_":[],"configs":[".developmentrc"],"config":".developmentrc"} //6、5和4一起运行 //nodeindex.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是配置入口文件,内容如下:
letrc=require('rc') //因为rc是从process.cwd()向上查找.appnamerc文件的,我们在根目录config文件夹里面的是找不到的,要改变工作路径到当前,再改回去 varoriginCwd=process.cwd() process.chdir(__dirname) varconf=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=productionnodeindex.js--database.password=tencent2019
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。