【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种方案,在项目具体采用哪种并没有绝对的说法,因地制宜即可。

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

相关推荐
小墨宝10 分钟前
js 生成pdf 并上传文件
前端·javascript·pdf
丘山子30 分钟前
一些鲜为人知的 IP 地址怪异写法
前端·后端·tcp/ip
CopyLower1 小时前
在 Spring Boot 中实现 WebSockets
spring boot·后端·iphone
www_pp_1 小时前
# 构建词汇表:自然语言处理中的关键步骤
前端·javascript·自然语言处理·easyui
YuShiYue1 小时前
pnpm monoreop 打包时 node_modules 内部包 typescript 不能推导出类型报错
javascript·vue.js·typescript·pnpm
天天扭码1 小时前
总所周知,JavaScript中有很多函数定义方式,如何“因地制宜”?(ˉ﹃ˉ)
前端·javascript·面试
一个专注写代码的程序媛2 小时前
为什么vue的key值,不用index?
前端·javascript·vue.js
장숙혜2 小时前
ElementUi的Dropdown下拉菜单的详细介绍及使用
前端·javascript·vue.js
.生产的驴2 小时前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
火柴盒zhang2 小时前
websheet之 编辑器
开发语言·前端·javascript·编辑器·spreadsheet·websheet