业务代码编写过程中如何「优雅的」配置隔离

news2024/12/23 13:24:39

思考

不同的处理方式

1.常规的处理方式,通过某种规则判断区分代码环境

// 获取环境标识
const env = getCurrentEnv();

if (env === 'dev') {// do something
} else if (env === 'test') {// do something
} else if (env === 'prod') {// do something
} 

分析:

1.此种方式强依赖 getCurrentEnv 方法区分环境,这里是_重点_;
2.强依赖 if else 中对于不同环境的处理逻辑;

缺点:

1.环境区分_强依赖代码逻辑_,并且各个_环境配置代码均存在于构建产物中_,
2.环境判断隔离,很难发现其他环境中的问题,代码出错或者改错,不易发现;

2.process.env.NODE_ENV 通过 node 运行时环境变量构建时区分代码环境

// 获取环境标识
const env = process.env.NODE_ENV;

if (env === 'dev') {// do something
} else if (env === 'test') {// do something
} else if (env === 'prod') {// do something
} 

分析:

1.此情况依赖构建脚本,不同环境增加构建环境变量,以此区分环境
2.其他情况_同上一条_

缺点:

1.需要多定制一次构建脚本,区分不同环境,也可使用 cross-env 追加环境脚本;
2.其他缺点_同上一条_

3.拆分环境配置代码到不同的配置文件,通过打包方式,固定只获取某个环境配置文件

/** 构建运行时环境配置 */
// $ cross-env ENV=test npm run build
// $ cross-env ENV=pre npm run build
// $ cross-env ENV=prod npm run build

// TEST:test.config.js
// PRE:test.config.js
// PROD:prod.config.js

// 这里需要改造打包代码,动态读取对应配置文件到某个全局变量中
const env = process.env.ENV;
// 动态读取对应环境配置文件
const config = require(`./config/${env}.config.js`);

// todo 通过编写构建代码动态添加到全局变量中 

分析:

1.此种情况_隔离了不同环境配置_,构建产物仅存在当前环境的代码配置,无冗余
2.一次编写构建配置,永久生效,仅需要维护不同环境配置文件即可,互不干扰;

缺点:

1.需要_定制构建代码_,_动态获取配置到全局变量_中,编写成本较高;
2.不利于运行时环境配置变更,每次改动配置需要重启构建脚本;

4.拆分环境配置代码到不同的配置文件,通过_动态生成各个环境配置文件_到本地_固定代码文件_中,在其他业务代码中固定引用此文件

/** 1. 定制脚本动态生成固定配置文件,此处需要定制 config 脚本,*.config.js 为环境配置文件,-s 对应源文件,-o 对应输出文件 */
// $ config -e dev -s ./config/dev.config.js -o src/config.js
// $ config -e test -s ./config/test.config.js -o src/config.js
// $ config -e prod -s ./config/prod.config.js -o src/config.js

// 读取生成的配置文件
import config from './config.js'; 

分析:

1.此情况唯一的难点在于_定制脚本动态生成不同的环境配置文件_;
2.生成的配置文件与其他环境解耦,且纯粹无冗余,并且有良好的运行时支持;

缺点:

1.定制脚本有些难度

思路小结

综上总结,为了解决冗余问题、环境干扰问题、维护变更问题、构建运行时问题等等,我比较推荐第 4 种方式,虽然有些定制难度,不过拆解下实现思路,其实还是有迹可循的:

1.定制一个_脚本_入口,可以_读取命令行中定义的入参_;
2._动态读取_配置文件,并_重写配置文件_到固定文件中;
3.应用;

下面我们就来一步一步实现该思路

实现

下面让我们来实现此功能

1. 定制脚本入口

这里需要完成几个功能点:

1.指定入口脚本文件
2.能够解析脚本入参

1.创建一个 config.js

console.log('> config 入口');
console.log('> ', process.argv); // 打印入参 

2.解析脚本入参,比如执行 node ./lib/config.js -e dev -o dist/config.js

> node ./lib/config.js -e dev -o dist/config.js

> config 入口
>['/usr/local/bin/node','/Users/fosunhealth/Documents/ME/learning-tools/packages/config/lib/config.js','-e','dev','-o','dist/config.js'
] 

观察以上打印即可根据出参匹配脚本入参规则,读取到自己想要的参数

  • 3.这里推荐下 commander 工具,封装了很多辅助功能,可以偷个懒
const program = require('commander');
const { version } = require('../package.json');

program.version(version)// .command('config') // 这里用作指定脚本名称,调试阶段可先注释.usage('-e <env> -o <output>').description('🍈 生成配置文件').option('-e, --env <env>', '当前环境').option('-o, --output <output>', '输出路径').action(({ output, env }) => {console.log('> 当前环境', env);console.log('> 输出路径', output);});

// 解析脚本入参
program.parse(process.argv); 

此时再执行脚本,得到输出结果如下:

得到了我们需要指定的环境变量,以及需要输出的路径,这阶段宣告完成

> node ./lib/config.js -e dev -o dist/config.js

> 当前环境 dev
> 输出路径 dist/config.js 

2. 动态读取配置文件,并生成到固定文件

接上一步,此阶段需要处理入参并动态输出配置文件:

1.根据 env 读取对应配置文件内容
2.写入到固定文件中

// 文件处理工具
const { existsSync, outputFileSync, mkdirSync, writeFileSync } = require('fs-extra');

/** 自定义规则读取本地的配置文件 */
const rootPath = process.cwd(); // 当前上下文根路径,这个很重要,需要基于当前上下文去寻找文件
const configPath = join(rootPath, `./config/${env}.config.js`); // 本地环境配置文件
const outputPath = join(rootPath, output || './src/config.ts'); // 生成配置路径

if (!existsSync(configPath)) {throw new Error(`${env} 环境配置文件不存在`);
}

try {// 读取配置内容const content = readFileSync(configPath, { encoding: 'utf-8' });// 写入配置内容writeFileSync(outputPath, content, { encoding: 'utf-8' });console.log('> 生成配置文件成功.');
} catch (error) {console.error('> 生成配置文件异常', error);
} 

如下图执行流程,即可动态生成所需环境配置了

1.这样实现具体的配置文件读取规则就可以自定义拉,也能在_业务代码构建过程中动态生成_了
2.使用方式还可以通过_封装到私库中_,通过脚本引用,这样就能当做一个_团队工具_使用了

源码参考:github.com/howieyi/lea…

基于以上,其实还有很多场景可以扩展,这里更多的是提供一种思路,希望对大家有所帮助。

最后

最近找到一个VUE的文档,它将VUE的各个知识点进行了总结,整理成了《Vue 开发必须知道的36个技巧》。内容比较详实,对各个知识点的讲解也十分到位。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/370927.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux 操作系统——查看/修改系统时区、时间、本地时间修改为UTC

文章目录1.背景描述2.知识储备3.解决步骤1. 查看当前时区2.修改设置Linux服务器时区3.复制相应的时区文件&#xff0c;替换系统时区文件&#xff1b;或者创建链接文件4. 查看和修改Linux的时间5. 硬件时间和系统时间的 相互同步1.背景描述 最近一个项目日期采用java8的LocalDa…

你在公司混的差,可能和组织架构有关!

原创&#xff1a;小姐姐味道&#xff08;微信公众号ID&#xff1a;xjjdog&#xff09;&#xff0c;欢迎分享&#xff0c;非公众号转载保留此声明。如果你接触过公司的面试工作&#xff0c;一定见过很多来自大公司的渣渣。这些人的薪资和职位&#xff0c;比你高出很多&#xff0…

Delphi RSA加解密(二)

dll开发环境: Delphi XE 10.1 Berlin exe开发环境: Delphi 6 前提文章: Delphi RSA加解密(一) 目录 1. 概述 2. 准备工作 2.1 下载DEMO程序 2.2 字符编码说明 3. Cryption.dll封装 3.1 接口概况 3.2 uPub.pas单元代码 3.3 uInterface.pas单元代码 3.4 特别注意 4. 主程序…

如何选择合适的数字隔离器

随着数字隔离器在工业和汽车应用中的日益普及&#xff0c;从众多可用选项中选择最适合您系统的器件可能会让人不知所措。除了这一挑战之外&#xff0c;大多数数字隔离器在设计时都考虑了特定的系统要求和应用&#xff0c;让您需要对无穷无尽的规格和功能进行分类&#xff0c;以…

C++ sting类(一)各类操作

1、 C语言中的字符串C语言中&#xff0c;字符串是以\0结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;C标准库中提供了一些str系列的库函数&#xff0c;但是这些库函数与字符串是分离开的&#xff0c;不太符合程序设计的思想&#xff0c;而且底层空间需要用户自己管…

NEXUS 6P刷机安装Edxposed

刷机 abd等工具下载&#xff1a; https://developer.android.com/studio/releases/platform-tools?hlzh-cn 下载后配置环境变量 镜像下载&#xff1a; https://developers.google.com/android/images?hlzh-cn#angler Magisk下载 GitHub - topjohnwu/Magisk: The Magic M…

基于BP神经网络的衣服识别,BP神经网络详细原理,BP神经网络图像识别神经网络案例之19

目标 背影 BP神经网络的原理 BP神经网络的定义 BP神经网络的基本结构 BP神经网络的神经元 BP神经网络的激活函数&#xff0c; BP神经网络的传递函数 数据 神经网络参数 基于BP神经网络 性别识别的MATLAB代码 效果图 结果分析 展望 背影 人靠衣服马靠鞍&#xff0c;通过穿衣可…

Matlab字符串相关操作-拼接、格式化

常见的有三种方法&#xff1a;向量拼接、strcat函数和sprintf函数1、向量拼接在matlab中字符串本质上也是一个向量&#xff0c;可以通过矩阵运算来实现字符串的拼接&#xff0c;这里随便输入两个字符串a1和b1&#xff0c;用矩阵形式进行拼接&#xff1a;a1 I love;b1 Matlab…

Web项目部署环境搭建:JDK + Tomcat + IDEA

Web项目部署环境搭建&#xff1a;JDK Tomcat IDEA1.java JDK1.1 下载安装1.2 配置环境变量1.3 检查安装成功2. TomCat2.1 下载安装2.2 配置环境变量2.3 检查安装成功3.IDEA3.1 下载安装3.2 永久可得3.3 IDEA部署Tomcat出来混总是要还的&#xff0c;记得大学本科四年&#xff…

Protobuf 逆向解析两种方法

Protobuf 逆向解析两种方法一、Protobuf 的特征二、解析.bin文件显示原始数据法一&#xff1a;用 blackboxprotobuf 模块解析法二&#xff1a;使用 protoc 解析工具一、Protobuf 的特征 案例网址 Protocol buffers是一种语言无关、平台无关、可扩展的序列化结构数据的方法&…

计算机网络 — UDP协议(看这一篇就可以

UDP协议UDP是传输层的重要协议之一&#xff0c;另一重要协议为TCP协议。两者对比&#xff1a;TCP协议复杂&#xff0c;但传输可靠。UDP协议简单&#xff0c;但传输不可靠。UDP协议全称为&#xff1a;User Datagram Protocol&#xff08;用户数据报协议&#xff09;。它是一个简…

嵌入式 STM32 使用C语言打开读取歌曲目录

目录 一、C语言目录库函数 1、打开一个目录文件opendir() 2、readdir&#xff08;);读取目录下文件 3、建立链表保存读到的文件名 一、C语言目录库函数 目录库函数链接&#xff1a;http://wjhsh.net/qiny1012-p-8405394.html 1、打开一个目录文件opendir() opendir()函数…

JavaScript BOM操作

目录 前言 window 对象 location 对象 navigator 对象 screen 对象 history 对象 前言 BOM&#xff08;Browser Object Model&#xff09;指的是浏览器对象模型&#xff0c;它是 JavaScript 和浏览器之间的接口。通过 BOM&#xff0c;JavaScript 可以与浏览器窗口交互&…

【Linux】重定向原理dup2缓冲区

文章目录重定向原理输出重定向关于FILE解释输出重定向原理追加重定向输入重定向dup2缓冲区语言级别的缓冲区内核缓冲区重定向原理 重定向的本质就是修改文件描述符下标对应的struct file*的内容 输出重定向 输出重定向就是把本来应该输出到显示器的数据重定向输出到另一个文…

自己制作投票链接网上投票链接制作可以投票的链接制作

近些年来&#xff0c;第三方的微信投票制作平台如雨后春笋般络绎不绝。随着手机的互联网的发展及微信开放平台各项基于手机能力的开放&#xff0c;更多人选择微信投票小程序平台&#xff0c;因为它有非常大的优势。1.它比起微信公众号自带的投票系统、传统的H5投票系统有可以图…

RK3568平台开发系列讲解(设备驱动篇)Pinctrl子系统详解

🚀返回专栏总目录 文章目录 一、pinctrl子系统结构描述二、重要的概念三、主要的数据结构和接口沉淀、分享、成长,让自己和他人都能有所收获!😄 📢我们知道在许多soc内部包含有多个pin控制器,通过pin控制器的寄存器,我们可以配置一个或者一组引脚的功能和特性。Linux…

K8S篇之pod及生命周期

文章目录Pod 概览pod使用方式Pod 中如何管理多个容器Pod 和控制器Pod 模板Pod 更新与替换静态 Pod容器探针pod的生命周期Pod 阶段容器状态容器重启策略Pod 状况pod readinessGates容器探针检查机制execgrpchttpGettcpSocket探测结果探测类型livenessProbe&#xff08;存活探针&…

【JDK8新特性之Lambda表达式-案例实操】

一.JDK8新特性之Lambda表达式-案例实操 之前我们学习了Stream流相关的内容&#xff0c;如果想看的同学可以看一下之前的文章&#xff0c;接下来我们就来学习和Lambda表达式有关的内容。 二.Lambda表达式案例实操 2.1 最原始创建线程案例版本 创建一个新的线程&#xff0c;指定…

[docker]Sealer简介

文章目录安装创建集群清理集群本机免密登录镜像构建与运行KubefileSealer ImageClusterfilesealer是阿里开源的一款分布式应用打包交付运行的解决方案&#xff1b;通过把分布式应用及其所依赖的数据库、中间件等一起打包成一个集群镜像&#xff0c;解决复杂应用的交付问题。安装…

阿里云服务器部署SpringBoot+Vue项目(宝塔面板傻瓜式操作)

准备工作 一台服务器(我用的是阿里云)SpringBoot项目的jar包Vue项目的dist包 一、购买服务器 然后重置实例密码。 远程连接 登陆成功后安装宝塔面板 二、安装宝塔面板(无账号的注册一个账号) 地址&#xff1a;https://www.bt.cn/new/download.html 选择对应的镜像、不知道…