uni-app的APP环境和H5环境,怎么实现在不同环境下使用不同的配置? 类似 env.dev env.prod 多环境功能如何实现?
uni-app如何实现 process.env.NODE_ENV 根据运行环境自定义环境变量?
前言
- 【我开发的操作系统是 MacOS,若你的是 Windows 系统,里面涉及到指令的地方,我会尽量写上针对windows系统的官方文档链接】
- 我在一个uniapp实际项目代码中看到访问api地址的变量是前端写死的,每次发不同环境的包时,都要去修改这些变量
- 所以我就在好奇心的驱使下,探索了一下uniapp在多环境方面解决方案
- 先说下结论:uniapp在多环境方面解决方案非常尴尬😅,说它有吧,有那么点,但略显尴尬,跟没有一样😓!我通过挖掘官方资料,最终终于想到了个人感觉相对合理一点的方案
- 【接下来请看我整理出来的在 APP和H5 两种平台下的多环境处理方案,至于小程序之类的其他杂牌,也大同小异,若有啥不对,欢迎友好评论,感谢🙏】
方案整体说明
- uniapp在多环境方面的解决方案,仍然需要针对不同的平台,即 APP平台和H5平台的解决方案是不同的
- uni-app 的 process.env.NODE_ENV 是无法修改的,官方说明是开发运行时为 'development',打包构建运行时为 'production' ,所以直接放弃使用 process.env.NODE_ENV 吧,我各种尝试下来,觉得uniapp里的process.env.NODE_ENV在实际开发中几乎就是多余的(因为对于H5环境,官方提供的自定义扩展发包配置可以直接新增编译变量控制代码块,也就无需NODE_ENV了)
方案代码展示!!
第一步 -[APP环境]-【创建好APP环境通过指令打包需要用到的配置文件】
-
这些配置文件是用于通过 Hbuildx cli 来实现在终端中使用指令打包APP,因为若通过点击Hbuildx的菜单上发包按钮打包的话,每次都要输入不同的appid、证书和密码,太麻烦了,预制好这些文件,直接通过命令行操作就方便多了
-
【uniapp的cli分为两种(若想直接通过npm调用cli,就必须是通过vue+hbuilder cli创建的项目才行,而我遇到的项目是直接通过Builderx创建的,所以只能使用hbuilderx cli来执行命令)】:官方文档链接
-
如 configure-dev.json
json
{
"project": "eManufacture-app",
"platform":"ios,android",
"iscustom": false,
"safemode": false,
"android": {
"packagename":"com.abc.devxxxapp",
"androidpacktype":"0",
"certalias":"__UNI__A5B5E58",
"certfile":"/Users/abc/Documents/my-app/pub-package/androidfiles/certfile.keystore",
"certpassword":"adr111"
},
"ios": {
"bundle":"com.ab-c.dev-xxx-app",
"supporteddevice":"iPhone,iPad",
"profile":"/Users/abc/Documents/my-app/pub-package/iosfiles/ios.mobileprovision",
"certfile":"/Users/abc/Documents/my-app/pub-package/iosfiles/ios.p12",
"certpassword":"abc222"
},
"isconfusion":false,
"splashads":false,
"rpads":false,
"pushads":false,
"exchange":false
}
第二步【把发包命令和配置预制在package.json脚本中】
- 同时也为 H5 环境加上针对多环境的自定义扩展uniapp发包脚本配置(即 package.json 中的 "uni-app":{"scripts": {...}} 这部分)
-
- 可能你会想到为啥不给 APP 环境也配置自定义扩展发包配置呢?答:uniapp不支持(官方原话是"
目前仅限如下枚举值:
h5、
mp-weixin、
mp-alipay、
mp-baidu、
mp-toutiao、
mp-qq`")
- 可能你会想到为啥不给 APP 环境也配置自定义扩展发包配置呢?答:uniapp不支持(官方原话是"
- 自定义扩展uniapp发包脚本配置 官方说明文档
- 自定义扩展发包配置配置完成后,就能在【HbuildX菜单栏>发行>自定义发行】中使用了
- package.json
json
{
"scripts":{
"build-dev:app": "/Applications/HBuilderX.app/Contents/MacOS/cli pack --config /Users/abc/Documents/my-app/pub-package/configure-dev.json",
"build-dev:android": "/Applications/HBuilderX.app/Contents/MacOS/cli pack --config /Users/abc/Documents/my-app/pub-package/configure-dev-android.json",
"build-dev:ios": "/Applications/HBuilderX.app/Contents/MacOS/cli pack --config /Users/abc/Documents/my-app/pub-package/configure-dev-ios.json",
"build-stage:app": "/Applications/HBuilderX.app/Contents/MacOS/cli pack --config /Users/abc/Documents/my-app/pub-package/configure-stage.json",
"build-stage:android": "/Applications/HBuilderX.app/Contents/MacOS/cli pack --config /Users/abc/Documents/my-app/pub-package/configure-stage-android.json",
"build-stage:ios": "/Applications/HBuilderX.app/Contents/MacOS/cli pack --config /Users/abc/Documents/my-app/pub-package/configure-stage-ios.json",
"build-prod:app": "/Applications/HBuilderX.app/Contents/MacOS/cli pack --config /Users/abc/Documents/my-app/pub-package/configure-prod.json",
"build-prod:android": "/Applications/HBuilderX.app/Contents/MacOS/cli pack --config /Users/abc/Documents/my-app/pub-package/configure-prod-android.json",
"build-prod:ios": "/Applications/HBuilderX.app/Contents/MacOS/cli pack --config /Users/abc/Documents/my-app/pub-package/configure-prod-ios.json"
},
"uni-app": {
"scripts": {
"h5-dev": {
"title": "H5-APP-测试环境",
"BROWSER": "chrome",
"env": {
"UNI_PLATFORM": "h5"
},
"define": {
"H5-DEV": true
}
},
"h5-stage": {
"title": "H5-APP-测试环境",
"BROWSER": "chrome",
"env": {
"UNI_PLATFORM": "h5"
},
"define": {
"H5-STAGE": true
}
},
"h5-prod": {
"title": "H5-APP-正式环境",
"BROWSER": "chrome",
"env": {
"UNI_PLATFORM": "h5"
},
"define": {
"H5-PROD": true
}
}
}
},
}
第三步【代码中编写config脚本文件】
-
我项目中是把这些config文件放在了 /common/ 目录下使用的
-
你根据自己项目情况,把config脚本文件到到相应的目录下使用即可
-
env-dev.js
arduino
// dev 环境
export const BASE_URL_H5 = '/devapi'
export const BASE_URL_APP = 'https://aaa:8887/api'
- env-stage.js
js
// stage 环境
export const BASE_URL_H5 = '/stageapi'
export const BASE_URL_APP = 'https://aaa:8888/api'
- env-prod.js
arduino
// prod 环境
export const BASE_URL_H5 = '/prodapi'
export const BASE_URL_APP = 'https://aaa:8889/api'
- config.js
js
// ----------- APP 环境 --------------
// #ifdef APP-PLUS
// 通过创建多个 appid 实现区分多环境,其中 appid 是数组原因是:android 和 ios 的 appid 不同
const APPID_ENVS = {
APPID_DEV: ['com.abc.devxxxapp','com.ab-c.dev-xxx-app'], // 对应 dev 环境的 appid
APPID_STAGE: ['com.abc.stagexxxapp','com.ab-c.stage-xxx-app'], // 对应 stage 环境的 appid
APPID_PROD: ['com.abc.prodxxxapp','com.ab-c.prod-xxx-app'], // 对应 prod 环境的 appid
}
import { BASE_URL_APP as BASE_URL_APP_DEV } from './env-dev.js'
import { BASE_URL_APP as BASE_URL_APP_STAGE } from './env-stage.js'
import { BASE_URL_APP as BASE_URL_APP_PROD } from './env-prod.js'
// 【*】暴露函数
export const getAppConfig = () => {
let BASE_URL = ''
const { appid } = plus.runtime
if(APPID_ENVS.APPID_DEV.includes(appid)) {
BASE_URL = BASE_URL_APP_DEV
} else if(APPID_ENVS.APPID_STAGE.includes(appid)) {
BASE_URL = BASE_URL_APP_STAGE
} else if(APPID_ENVS.APPID_PROD.includes(appid)) {
BASE_URL = BASE_URL_APP_PROD
}
return {
BASE_URL
}
}
// #endif
// ----------- H5 环境 -> 以下这些编译变量都是自定义扩展的(在【HbuildX菜单栏>发行>自定义发行】中使用) --------------
// #ifdef H5-DEV
import { BASE_URL_H5 } from './env-dev.js'
const BASE_URL = BASE_URL_H5
// #endif
// #ifdef H5-STAGE
import { BASE_URL_H5 } from './env-stage.js'
const BASE_URL = BASE_URL_H5
// #endif
// #ifdef H5-PROD
import { BASE_URL_H5 } from './env-prod.js'
const BASE_URL = BASE_URL_H5
// #endif
// #ifdef H5
// 【*】暴露函数
export const getAppConfig = () => {
return {
BASE_URL
}
}
// #endif
- 【以上3步其实就是多环境配置的核心方案了,接下来的步骤,主要是针对前端访问接口的 BASE_URL 控制了 】
*额外步骤*
第三步 -[针对H5环境]-【nginx代理配置】
-
上面我们在 H5 环境代码块中,配置的 BASE_URL 是
/devapi
这样的,这是为了可以把实际访问接口的控制权放到服务端,这样可以避免当需要更改接口地址时,就不需要前端重写打包了,若接口地址写死在前端代码中,那一旦需要修改接口地址,就又要重写打包,重新部署,这就没必要了 -
对于 APP 来说,我这边给到的方案是,也在服务端配置不同的 nginx 反向代理来转到实际的接口地址中,目的同上,对于APP来说重新打包就意味着要用户更新,而对于这种接口地址修改的问题,更要避免让用户去更新(所以我在不同的环境配置中写了不同的接口地址
BASE_URL_APP = 'https://aaa:8887/api
BASE_URL_APP = 'https://aaa:8889/api
BASE_URL_APP = 'https://aaa:8887/api
) -
[针对H5]nginx.conf 案例代码(这份配置需要根据你项目情况来定了,这里写的仅供参考)
bash
server {
listen 80;
server_name localhost;
location /devapi/ {
rewrite /devapi/(.*) /$1 break;
proxy_pass https://abcsys.com:7777;
proxy_set_header Host $host;
proxy_method $request_method;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
if ($request_uri ~ ^/api/) {
break;
}
}
}
- [针对APP]nginx.conf 案例代码(这份配置需要根据你项目情况来定了,这里写的仅供参考)
ini
server {
listen 8887;
server_name localhost;
location /api/ {
proxy_pass https://abcsys.com:7777;
proxy_set_header Host $host;
proxy_method $request_method;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
*额外步骤*
第四步 -[H5部署]-【dockerfile参考】
- dockerfile
dockerfile
FROM nginx
# 拷贝web应用目录到容器目录
COPY /unpackage/dist/build/h5 /usr/share/nginx/html
# 拷贝自定义配置文件
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 暴露端口
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# 创建镜像和容器指令
# docker build -t my-nginx:v1 .
# docker run -d --name my_nginx_container -p 8180:80 my-nginx:v1
- 这里用到的 nginx.conf 内容如下:
nginx.conf
server {
listen 80;
server_name localhost;
location /devapi/ {
# 重写前端代码中访问接口url /devapi/aaa/bbb 中的 /devapi/ 这部分,变为 /aaa/bbb
# 和下面这句 proxy_pass https://abcsys.com:7777 组合效果最终就会把 /devapi/aaa/bbb 变为 https://abcsys.com:7777/aaa/bbb
rewrite /devapi/(.*) /$1 break;
proxy_pass https://abcsys.com:7777;
proxy_set_header Host $host;
proxy_method $request_method;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
# 加这句是为例解决web部署后发生2次请求
if ($request_uri ~ ^/devapi/) {
break;
}
}
}