uni-app自定义多环境配置,动态修改appid
背景
在企业级项目开发中,一般都会分为开发、测试、预发布、生产等多个环境,在工程化中使用不同的打包命令改变环境变量解决不同环境各种变量需要手动修改的问题,比如接口请求地址,不同环境的请求路径前缀都是不同的。在使用uni-app
开发项目时,一般都是选择使用HbuilderX
可视化创建项目,也不建议使用cli
工程化方式创建uni-app
项目。在HbuilderX
中,默认只支持开发和生产两个环境,点击“运行”编译出来的代码是开发环境(development
),点击“发行”编译出来的代码是生产环境(production
),可以通过process.env.NODE_ENV
获取当前环境。但在很多企业中,可能就2个环境并不能满足实际场景,同时在开发微信小程序时,测试和生产都是不同的appid
,每次部署都要手动修改切换很容易出现问题。为了解决上述问题,通过在package.json
中增加uni-app
扩展节点,实现自定义条件编译平台,让每种编译具有不同环境标识。再扩展vite.config.js
配置文件,用环境标识判断重写文件中的appid
。
解决方案
一、创建基础项目
选择默认模板,注意vue版本选择3
二、增加扩展节点
根据官方文档说明,扩展节点配置说明如下:
{/*** package.json其它原有配置 * 拷贝代码后请去掉注释!*/"uni-app": {// 扩展配置"scripts": {"custom-platform": { //自定义编译平台配置,可通过cli方式调用"title":"自定义扩展名称", // 在HBuilderX中会显示在 运行/发行 菜单中"browser":"", //运行到的目标浏览器,仅当UNI_PLATFORM为h5时有效"env": {//环境变量"UNI_PLATFORM": "", //基准平台"MY_TEST": "", // ... 其他自定义环境变量},"define": { //自定义条件编译"CUSTOM-CONST": true //自定义条件编译常量,建议为大写}}}}
}
注意:
UNI_PLATFORM
仅支持填写uni-app
默认支持的基准平台,目前仅限如下枚举值:h5
、mp-weixin
、mp-alipay
、mp-baidu
、mp-toutiao
、mp-qq
browser
仅在UNI_PLATFORM
为h5
时有效,目前仅限如下枚举值:chrome
、firefox
、ie
、edge
、safari
、hbuilderx
package.json
文件中不允许出现注释,否则扩展配置无效vue-cli
需更新到最新版,HBuilderX需升级到 2.1.6+
实际使用时,暂时不用的变量直接删除,新建package.json
文件,代码如下:
{"uni-app": {"scripts": {"wx-test": {"title":"微信小程序 测试环境","env": {"UNI_PLATFORM": "mp-weixin","NAME": "test"}},"wx-prod": {"title":"微信小程序 生产环境","env": {"UNI_PLATFORM": "mp-weixin","NAME": "production"}},"h5-dev": {"title":"H5 开发环境","browser":"chrome","env": {"UNI_PLATFORM": "h5","NAME": "development"}},"h5-test": {"title":"H5 测试环境","browser":"chrome","env": {"UNI_PLATFORM": "h5","NAME": "test"}},"h5-prod": {"title":"H5 生产环境","browser":"chrome","env": {"UNI_PLATFORM": "h5","NAME": "production"}}}}
}
上面代码片段只以微信小程序和H5
两个端为例,其中只增加了常量NAME
用于区分当前环境,类似于process.env.NODE_ENV
获取环境变量的作用。一般小程序也就测试和生产两个环境,环境太多都要重新申请账号也麻烦。H5
按照常规的配置本地开发、测试、生产三个环境。配置好后我们点击顶部菜单栏的“运行”和“发行”即可看到效果。
当在业务里需要使用添加的NAME
变量时,直接通过process.env.NAME
即可获取。
四、配置其他变量
根目录下新建config
目录,用于放一些业务配置项,再新建环境相关变量配置文件env.js
,代码如下:
// 不同的环境变量配置
const development = {requestBaseUrl: 'http://development', appid: '',
}const test = {requestBaseUrl: 'http://test',appid: 'wxd5xxxxee0fce1c81',
}const production = {requestBaseUrl: 'http://production',appid: 'wx3xxxx1ce403cab3',
}export default {development,test,production
}
其中变量对象名称development
、test
、production
要和package.json
文件中定义的NAME
保持一致,方便后续通过对象方式直接取值。变量对象中添加的是需要根据不同环境配置的变量,比如后端服务请求地址,小程序appid
和一些别的插件key
。配置后我们就可以配合环境NAME
获取到不同环境的其他变量了,简单使用方式如下:
import ENV_CONFIG from '@/config/env.js'
console.log(ENV_CONFIG[process.env.NAME].requestBaseUrl) // 运行H5 开发环境结果 http://development
每次引入获取方式肯定不够友好,在uni-app
中还可以通过修改vite
配置添加全局变量,更方便在全局使用。
首先根目录下新建vite.config.js
文件,内容如下:
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import ENV_CONFIG from './env/index.js'export default defineConfig({plugins: [uni()],define: {'process.env.config': ENV_CONFIG,},
});
通过定义一个全局变量process.env.config
,赋值为ENV_CONFIG
,process.env.config
可以改为任何一个字符串,这里主要是为了保持和默认通过process.env
获取环境变量的语义一致性。此时使用时就无需在业务中单独引入,从全局对象process.env.config
上取值即可:
console.log(process.env.config[process.env.NAME].requestBaseUrl) // 运行H5 开发环境结果 http://development
五、动态修改小程序appid
appid
是在根目录下的manifest.json
文件中,点击后最下面有源码视图。修改的方式就是运用node
的fs
模块,先读取manifest.json
文件,然后根据当前环境,动态替换掉appid
或者其他参数,最后重新写入到当前目录下。具体也是在vite.config.js
中处理:
import { defineConfig } from 'vite';
import uni from '@dcloudio/vite-plugin-uni';
import ENV_CONFIG from './config/env.js'// 引入fs模块
import fs from 'fs'// 读取 manifest.json ,修改后重新写入
const manifestPath = `${__dirname}/manifest.json`;
let Manifest = fs.readFileSync(manifestPath, { encoding: 'utf-8' });
function replaceManifest(path, value) {const arr = path.split('.');const len = arr.length;const lastItem = arr[len - 1]; let i = 0;let ManifestArr = Manifest.split(/\n/);for (let index = 0; index < ManifestArr.length; index++) {const item = ManifestArr[index];if (new RegExp(`"${arr[i]}"`).test(item)) ++i;if (i === len) {const hasComma = /,/.test(item);ManifestArr[index] = item.replace(new RegExp(`"${lastItem}"[\\s\\S]*:[\\s\\S]*`),`"${lastItem}": ${typeof value === 'string'? '"'+value+'"' : value}${hasComma ? ',' : ''}`);break;}}Manifest = ManifestArr.join('\n');
}
// 具体使用,找到对应key值替换为新的值
// replaceManifest('app-plus.usingComponents', false);const appid = ENV_CONFIG[JSON.parse(process.env.UNI_CUSTOM_DEFINE).NAME].appid
replaceManifest('mp-weixin.appid', appid);fs.writeFileSync(manifestPath, Manifest, { flag: 'w' });export default defineConfig({plugins: [uni()],define: {'process.env.config': ENV_CONFIG,},
});
这个修改方案是根据官方提供的代码片段修改,其中进行了一些变动:
manifest.json
文件路径由相对路径改为__dirname
获取的绝对路径replaceManifest
方法中的value进行了typeof
类型判断,如果是字符串加上双引号。因为测试时传个字符串会替换成没引号的变量或者数字
同时关于当前环境变量的获取,此时通过process.env.NAME
是获取不到package.json
配置的NAME
的,通过打印process.env
可以发现此时它是个包含很多变量的json
,在UNI_CUSTOM_DEFINE
下面是可以找到NAME
,这样就能根据不同环境获取不同的appid
。
然后也可以用下面这种更容易理解的方式修改manifest.json
,但是修改后内容排在一行,想要美观还需要手动格式化。
// appid获取只做参考,这里只是说明简单的只有两个环境,可以直接取process.env.NODE_ENV判断
let appid = process.env.NODE_ENV == "production" ? '生产的appid' : "开发的appid"
// manifest.json 路径
let manifestFileUrl = `${__dirname}/manifest.json`
// 读取文件数据
let manifestFileData = fs.readFileSync(manifestFileUrl, { encoding: 'utf8' });
// 移除// 和 /* */注释
manifestFileData = manifestFileData.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (m, g) => g ? "" : m)
// // 将txt转成obj
let manifestFileDataObj = JSON.parse(manifestFileData)
// 修改指定key对应的valuemanifestFileDataObj['mp-weixin']['appid'] = appid
// 把修改后的对象以json写入文件
fs.writeFileSync(manifestFileUrl, JSON.stringify(manifestFileDataObj), { encoding: 'utf8' })
六、使用方式
- 需要本地调试时,点击工具栏“运行”,选择自定义的对应开发或测试环境;
- 业务中通过
process.env.config[process.env.NAME]
获取配置的变量对象; - 上线时,点击工具栏“发行”,选择自定义的对应测试或生产环境;
运行环境
以上代码是运行在Hbuilderx 3.7.9
版本,项目为vue3
版本,基于vite
构建。如在vue2
版本上使用,请按照vite.config.js
逻辑自行探索配置vue.config.js
文件。
相关文章:

uni-app自定义多环境配置,动态修改appid
背景 在企业级项目开发中,一般都会分为开发、测试、预发布、生产等多个环境,在工程化中使用不同的打包命令改变环境变量解决不同环境各种变量需要手动修改的问题,比如接口请求地址,不同环境的请求路径前缀都是不同的。在使用uni-…...

04 - 分离头指针情况、理解HEAD和branch
查看所有文章链接:(更新中)GIT常用场景- 目录 文章目录 1. 分离头指针2. HEAD和branch2.1 branch的一些操作2.2 HEAD 1. 分离头指针 分离头指针detached HEAD是一种HEAD指针指向了某一个具体的 commit id,而不是分支的情况。 切换…...

C#__基本特性和使用
// 特性(attribute): // 一种允许我们向程序集添加元数据的语言结构 // 用于保存程序结构信息的某种特殊类型的类 // 类似“批注”,用于解释说明 #define IsShowMessage // 宏定义,在开头定义࿰…...
mysql(3)
分库分表 分库:将数据库中的数据分散到不同数据库上,可以垂直分库和水平分库。 1.垂直分库:把单一的数据按照业务进行划分,不同的业务使用不同的数据库,进而将一个数据库的压力分散到多个数据库。 2.水平分库&#…...
阿里巴巴常用的12个后端开发工具
1 阿尔萨斯Java在线诊断工具 Arthas是一款用于Java应用程序的在线诊断工具,由阿里巴巴于2018年9月开源。 典型场景: 您不知道从中加载类的特定JAR包。 您想弄清楚为什么您的系统会抛出各种与类相关的异常。 您不知道为什么修改后的代码无法执行。您不…...

php base64转图片保存本地
调用函数 public function base64(){$img $this->request->param(img);$img data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAkACQAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy…...

unity物体移动至指定位置
物体坐标与物体移动 世界坐标与局部坐标之间的转换物体移动至指定位置需求思路注意 世界坐标与局部坐标之间的转换 在Unity中,物体的坐标分为局部坐标和世界坐标。 局部坐标是相对于物体的父对象的坐标系,而世界坐标是相对于场景的整体坐标系。 使用tr…...

详解C#-static void Main(string[] args)
目录 简介: 举例: 输出结果:编辑 总结: 简介: 在C#中static void Main(string[] args)这个句话有什么作用,分别代表什么意思!! 这句话是入口函数的声明,指定了C#程序的入口点,并定义了一个名为”Mai…...

中大许少辉博士《乡村振兴战略下传统村落文化旅游设计》中国建筑工业出版社八一付梓。
中大许少辉博士《乡村振兴战略下传统村落文化旅游设计》中国建筑工业出版社八一付梓。...

Matplotlib数据可视化(五)
目录 1.绘制折线图 2.绘制散点图 3.绘制直方图 4.绘制饼图 5.绘制箱线图 1.绘制折线图 import matplotlib.pyplot as plt import numpy as np %matplotlib inline x np.arange(9) y np.sin(x) z np.cos(x) # marker数据点样式,linewidth线宽,li…...
Python爬虫——requests_post请求
import requests import jsonurl https://fanyi.baidu.com/sugheaders {User-Agent: ,Cookie: }data {kw: hello }response requests.post(url, data, headersheaders)content response.textobj json.loads(content.encode(utf-8)) print(obj)总结: post请求…...

excel 下载方法封装
1.首先需要拿到后端返回的URL下载地址 2.写个下载方法 // url 接口返回的下载地址。例如:https://cancer-research.oss-cn-beijing.aliyuncs.com/yuance-platform-permission/校内共享数据导入模板.xlsx // name 文件名称 例如: 校内共享数据导入模板 /…...
按日,周,月,季,年统计;获取对应的时间段
按日,周,月,季,年统计;获取对应的时间段 1.周实体类:WeekEntity.java package com.test.common.entity;import java.time.LocalDate;public class WeekEntity {private String day;/*** 开始日期**/privat…...

【eNSP】交换机(vlan和vlan间通信)
【eNSP】交换机(vlan和vlan间通信) 原理术语过程 实验根据图片连接模块配置设备名称和IP地址配置交换机交换机链路指定sw1配置sw2配置 设置网关交换机互联实验设置查看设置结果 ospf配置 原理 HUB集线器:它的作用可以简单的理解为将一些机器…...

2011年下半年 软件设计师 上午试卷2
博主介绍:✌全网粉丝3W,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验…...
Linux中安装MySQL8版本,安装MySQL步骤,MySQL8离线安装
Linux中安装MySQL8版本的步骤如下: 1.检查下libaio.so.1的位置 [roottdx ]# whereis libaio.so.1 libaio.so: /usr/lib64/libaio.so.1 如果没有找到该文件 (1).在线安装 [roottdx ]# yum install -y libaio (2).离线安装: 上传之后执行命令安装&#…...

MES生产管理系统如何与ERP系统集成
MES生产管理系统和ERP企业管理系统是制造企业信息化的重要组成部分,它们在生产管理、资源计划和业务流程等方面发挥着重要作用。实现MES与ERP系统的集成,可以更好地优化企业生产流程,提高生产效率和降低成本。本文将探讨MES管理系统解决方案如…...
Kafka如何保证消息⼀定能被消费
Kafka 通过多种机制来保证消息一定能被消费,从而实现数据的可靠性和持久性。 以下是一些常见的方法和策略来提高消息的可靠性: 复制机制: Kafka 使用了分区和副本的概念。每个分区可以有多个副本,分布在不同的 Broker 上。当消息…...

[USACO1.5] 八皇后 Checker Challenge
题目描述 一个如下的 6 x 6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。 上面的布局可以用序列 2 4 6 1 3 5 来描述,第…...

【Mysql】MVCC版本机制的多并发
🌇个人主页:平凡的小苏 📚学习格言:命运给你一个低的起点,是想看你精彩的翻盘,而不是让你自甘堕落,脚下的路虽然难走,但我还能走,比起向阳而生,我更想尝试逆风…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...