【Express.js】全局变量与配置文件

全局变量与配置文件

通常我们会将一些项目的配置信息写在一个文件内,然后读入内存并使用。在 express 中使用全局变量有多种方案,我们一起看看有哪些常用的方案

准备工作

拷贝第一节的HelloWorld项目

准备一个Resp.js模块:

js 复制代码
module.exports = {
    Ok: (...args)=>{
        return {
            code: 200,
            msg: args[0]?args[0]:"Ok",
            data: args[1]?args[1]:null
        }
    }
}

global

global对象中挂载我们需要全局共享的量,比如我们想要挂载一个全局的config作为整个express应用的配置,就在项目的唯一入口文件(如: index.js, app.js等)的最顶上(优先于任何模块)设置一次:

js 复制代码
// index.js
global.config = {
    appname: "GlobalVar"
}
/** 更简洁的写法,隐变量,首次被执行到后,会自动挂载到全局
config = {
    appname: "GlobalVar"
}
*/
//创建app应用...

这样我们就可以在其它任何地方调用config,比如新建一个router.js挂载到express应用上去

js 复制代码
// router.js
const routes = require('express').Router();
routes.get('/global', (req, res, next)=>{
    res.send(Resp.Ok("global中的全局变量", {"appname":config.appname}));
});

module.exports = routes;

// index.js
app.use(routes);

如果我们有很多需要全局共享的配置,挤在index.js的上方多少有点不雅观,那我们可以把它们写在一个文件里,然后在index.js最顶上引入一下

js 复制代码
// global.js
global.config = {
    appname: "GlobalVar"
}

// index.js
require('./global');

**注意:**由于global中的变量是可以直接以变量名xxx调用的,无需global.xxx,如果变量名设置的比较普通,就比如上面的config,甚至更简单的a之类的,很可能跟其它模块中定义的临时变量冲突,造成变量污染,因此在global上挂载变量时取名一定要特殊点,比如:之前的config替换为__config

js 复制代码
global.__config = {
    appname: "GlobalVar"
}

优点:

  • 调用很便捷

缺点:

  • 可能变量污染
  • 没有代码提示,不心安

module

自定义一个module,存放一些变量,在需要的地方进行引入

比如:我们自建一个config.js

js 复制代码
// config.js
module.exports = {
    appname: "GlobalVar"
}

在router.js中引入config.js

js 复制代码
// router.js
const CONFIG = require('./config');

routes.get('/module', (req, res, next)=>{
    res.send(Resp.Ok("config模块当作全局变量", {"appname":CONFIG.appname}));
});

优点:

  • 能有代码提示
  • 无变量污染

缺点:

  • 每次都要引入,比较麻烦

app.set

在 express 的应用设置表中设置应用内的全局变量:

js 复制代码
// index.js
app.set("appname", "GlobalVar");

在其它地方调用app,如挂载在app上的router:

js 复制代码
// router.js
routes.get('/app', (req, res, next)=>{
    res.send(Resp.Ok("app中的'全局'变量", {"appname":req.app.get("appname")}));
});

在挂载在app下的子应用中,调用父app中的设置,当某字段在子应用中没有设置时,会继承父应用中的字段

js 复制代码
//subapp.js
const app = require('express')();
const Resp = require('./Resp');
//当子应用没有设置时,会继承父应用中设置的字段
// app.set('appname', "subapp");
app.all('/', (req, res, next) => {
    res.send(Resp.Ok("子应用获取父应用中的全局变量", {
        appname: req.app.get("appname")
    }));
})

module.exports = app;

//index.js
const subapp = require('./subapp');
app.use('/subapp',subapp);

优点:

  • 能有代码提示

process.env

在进程的环境变量中挂载全局变量:

js 复制代码
//index.js
process.env.appname = "GlobalVar";

在其它地方调用process.env.appname

js 复制代码
// subapp2.js
const app = require('express')();
const Resp = require('./Resp');

app.all('/', (req, res, next) => {
    // console.log(app.settings.env);
    res.send(Resp.Ok("在process.env上挂载全局变量", {
        appname: process.env.appname
    }));
})

module.exports = app;

//index.js
const subapp2 = require('./subapp2');
app.use('/process.env',subapp2);

缺点:

  • 没有代码提示,不心安

json

以上的方案都是将配置信息写在js文件中的,对于一个正规的项目来说多少有点儿戏,毕竟写在js中的变量是很容易就能被改变的。绝大多数时候,配置信息是需要变化也不允许变化的,我们只需要静态的信息即可。在Js项目中,经常用json文件作为静态配置文件。

新建一个config.json文件:

json 复制代码
{
	"appname": "GlobalVar"
}

在我们的router中新加一条测试一下,不管你在哪里require,在首次被require之后,修改json文件内容将不会再产生影响

JS 复制代码
routes.get('/json', (req, res, next)=>{
    let configJson = require('./config.json');
    res.send(Resp.Ok("json静态配置文件", {"appname":configJson.appname}));
});

json文件不支持注释,如果想要注释,要么曲线救国(加与被备注键相关的键值对),要么使用Json5规范

shell 复制代码
npm install json5

新建一个config.json5文件:

json5 复制代码
{
    "appname": "GlobalVar"  //应用名
}

接着在项目的入口文件中引入register,会挂载到全局:

js 复制代码
require('json5/lib/register');

之后require就可以解析json5文件了:

js 复制代码
routes.get('/json5', (req, res, next)=>{
    let configJson5 = require('./config.json5');
    res.send(Resp.Ok("json5静态配置文件", {"appname":configJson5.appname}));
});

yaml

相比.json文件,.yaml(或.yml)文件是更加现在的配置文件,json文件有着严格的格式要求,yaml(yml)书写起来则更加自然

新建一个config.yaml文件:

yaml 复制代码
# 应用名
appname: GlobalVar  # 应用名

在nodeJs中读取yaml需要借助fsjs-yaml

shell 复制代码
npm install fs
npm install js-yaml

把fs挂载到全局即可(之前的global.js),一般情况下也不会取fs这样的局部变量名,如果需要频繁的操作文件,挂载到全局后会方便很多:

js 复制代码
global.fs = require('fs');

在router.js中引入js-yaml并新建一个测试路由:

js 复制代码
const yaml = require('js-yaml');

routes.get('/yaml', (req, res, next)=>{
    /*Object */
    let configYaml = yaml.load(fs.readFileSync('./config.yaml'));
    res.send(Resp.Ok("yaml动态配置文件", {"appname":configYaml.appname}));
});

由于是通过fs读取yaml文件的,因此在改变yaml文件中的内容后,访问路由的结果也会变


本文总共介绍了6种方案,在项目具体采用哪种并没有绝对的说法,因地制宜即可。

下一节-错误分类和日志分级

相关推荐
土豆湿8 分钟前
拥抱极简主义前端开发:NoCss.js 引领无 CSS 编程潮流
开发语言·javascript·css
J总裁的小芒果16 分钟前
Vue3 el-table 默认选中 传入的数组
前端·javascript·elementui·typescript
Lei_zhen9619 分钟前
记录一次electron-builder报错ENOENT: no such file or directory, rename xxxx的问题
前端·javascript·electron
辣条小哥哥20 分钟前
electron主进程和渲染进程之间的通信
javascript·electron·ecmascript
咖喱鱼蛋21 分钟前
Electron一些概念理解
前端·javascript·electron
yqcoder22 分钟前
Vue3 + Vite + Electron + TS 项目构建
前端·javascript·vue.js
草莓base28 分钟前
【手写一个spring】spring源码的简单实现--容器启动
java·后端·spring
Ljw...43 分钟前
表的增删改查(MySQL)
数据库·后端·mysql·表的增删查改
编程重生之路43 分钟前
Springboot启动异常 错误: 找不到或无法加载主类 xxx.Application异常
java·spring boot·后端
薯条不要番茄酱44 分钟前
数据结构-8.Java. 七大排序算法(中篇)
java·开发语言·数据结构·后端·算法·排序算法·intellij-idea