注意:文章中使用的 HBuilderX 版本为
4.24
。
使用 HBX 创建的 uni-app
项目(非CLI创建),想要定义环境变量一直是一个让人非常困扰的事情。
官方的文档 关于环境变量的说明也非常暧昧不清。
通过关键词 环境变量
检索会出现5篇相关文档:
- #配置环境变量 - vue.config.js | uni-app官网
- #判断平台 - 开发环境和生产环境 | uni-app官网
- #环境变量 - Vue2升3指南 | uni-app官网
- 编辑器配置 | uni-app官网
- 真机运行常见问题@run | uni-app官网
所以我早期定义环境变量就是使用的第一个文档链接中使用 DefinePlugin 来定义环境变量的方式
// vue.config.js
module.exports = {
chainWebpack: config => {
config
.plugin('define')
.tap(args => {
args[0]['process.env'].MY_TEST = '"test"' // 注意需要多层引号包裹
return args
})
}
}
注意:注意需要多层引号包裹自定义环境变量的值。
const test = process.env.MY_TEST // test
console.table(process.env)
// (索引) 值
// NODE_ENV development
// VUE_APP_NAME Test-Project
// VUE_APP_PLATFORM h5
// BASE_URL /
// MY_TEST test
我这边在声明环境变量时,不需要使用
VUE_APP_
这样的前缀,但是官方的示例中是有的。如果你无法在业务代码中正确获取到,可以尝试添加VUE_APP_
前缀(👉VUE_APP_MY_TEST
)
😣 出现问题
在 chainWebpack
链中使用 DefinePlugin
就能定义环境变量和使用了,并且项目正常运行了2年。
直到现在有一个 比较大的需求变动 需要新增一个环境变量。
看起来很简单是吧,这不是只需要在原本定义环境变量的地方新增一个环境变量就行了吗?但这篇文章的出现就说明了并没有那么简单😂。
我在业务代码中使用新增环境变量时出现了问题,会抛出 xxx is not defined
的情况。不管我是直接使用 process.env.VUE_NEW_VAR
还是使用 console.log(process.env)
查看所有环境变量都会在控制台抛出异常。
但是项目中之前已经声明的环境变量的使用并不会出现异常,只有我新增的环境变量后才会遇到。非常困扰 😭
配置如下:
// vue.config.js
module.exports = {
chainWebpack: config => {
config
.plugin('define')
.tap(args => {
args[0]['process.env'].BASE_URL = '"/"';
args[0]['process.env'].BASE_API_PREFIX = '"/api"';
args[0]['process.env'].BASE_APP_TITLE = '"TEST PROJECT"';
args[0]['process.env'].DEFAULT_SERVER = 'cn'; // 👈
return args
})
}
}
🤡 解决问题
其实出现这个问题的原因非常简单,我相信细心的小伙伴已经发现了。
就是我在声明新环境变量的时候没有使用多层引号包裹 '"cn"'
,直接用的 'cn'
才导致的这个问题。
所以稍作修改就可以修复这个异常了:
- args[0]['process.env'].DEFAULT_SERVER = 'cn'
+ args[0]['process.env'].DEFAULT_SERVER = '"cn"'
但! 其实我在准备写这篇文章的时刻并没有发现。写到一半的时候才突然发现自己这个好蠢的错误😂
不过其实就算不遇到问题,其实使用 DefinePlugin
来设置环境变量的方式也已经满足不了我现在的业务需求了。需要改用 自定义编译平台配置 的方式来定义不同的环境变量。
🤲 在自定义编译平台配置中定义环境变量
因为现在的需求是需要按照不同的服务器所在地区,做默认目标服务器的配置的。分流到国内服务的需要默认请求到国内服务上,分流到欧洲服务的需要默认请求到部署在欧洲的服务上。原本使用 DefinePlugin
来设置环境变量的方式,没办法在 HBX 发行时定义环境变量模式。只能基于 NODE_ENV
的不同来区分 development
和 production
两种编译模式来做一些业务判断。
改造起来也很简单,把原本在 vue.config.js
中定义的环境变量都迁移到 package.json
中就行了。
// package.json
{
... // 其他项目配置,
"uni-app": {// 扩展配置
"scripts": {
"server-CN": { //自定义编译平台配置,可通过cli方式调用
"title": "国内环境", // 在HBuilderX中会显示在 运行/发行 菜单中
"env": {// 环境变量
"UNI_PLATFORM": "h5", // 基准平台
// 自定义环境变量,注意:需要由 `UNI_` 前缀
"UNI_BASE_URL": "/",
"UNI_API_PREFIX": "/api/cn",
"UNI_APP_TITLE": "TEST PROJECT",
},
},
"server-EU": { //自定义编译平台配置,可通过cli方式调用
"title": "欧洲环境", // 在HBuilderX中会显示在 运行/发行 菜单中
"env": {// 环境变量
"UNI_PLATFORM": "h5", // 基准平台
// 自定义环境变量,注意:需要由 `UNI_` 前缀
"UNI_BASE_URL": "/",
"UNI_API_PREFIX": "/api/eu",
"UNI_APP_TITLE": "TEST PROJECT",
},
}
}
}
}
注意:自定义环境变量需要有
UNI_
前缀,这个在官方文档中并没有提到。
声明好之后在 HBX 的菜单中选择 [运行 - 国内环境] 中启动对应的自定义编译配置,就可以在项目业务中获取到对应的环境变量了。
const test = process.env.UNI_API_PREFIX // /api/cn
但是并不会像在 DefinePlugin
中声明的环境变量那样,可以在 process.env
查看到所有定义的自定义环境变量信息。只会输出默认环境变量 👇
console.table(process.env)
// (索引) 值
// NODE_ENV development
// VUE_APP_NAME Test-Project
// VUE_APP_PLATFORM h5
// BASE_URL /
可以看到并没有输出我定义的 UNI_BASE_URL
、UNI_API_PREFIX
和 UNI_APP_TITLE
这三个环境变量。
这个部分没有能在文档中找到相关的说明。但是在一个 Vue3+Vite项目使用环境变量的问题 中,DCloud官方维护人员给出了一个解释:
应该直接访问
process.env.*
的具体内容,比如process.env.NODE_ENV
(要么是内置好了,要么是自己define
了),不支持访问process.env
,因为vite
里边除了dev:h5
,其他环境是直接替换完整的字符串。可以使用标准vite
项目做测试
所以猜测使用自定义编译平台配置定义的环境变量,在项目运行和构建时 HBX 也是一样的方式通过 env-key
直接进行文本替换的。
在另外的一个问答中也验证了我的这个想法 👉 根据官方文档,在package.json定义了自定义环境变量,为什么在代码中获取不到呢,正确的获取方式是什么样的呢 - DCloud问答
P.S. 如果依然没有生效,可以尝试同时声明多个不同前缀的环境变量,看看哪一个可以在你使用的环境变量定义的方式中生效。
比如说:
"UNI_API_PREFIX": "/api/cn",
"VITE_API_PREFIX": "/api/cn",
"VUE_APP_API_PREFIX": "/api/cn",
并且直接在业务代码中使用 process.env.UNI_API_PREFIX
,而不是输出整个 process.env
查看。
相关资源
环境变量 | uni-app官网
编辑器配置 | uni-app官网
开发环境和生产环境 | uni-app官网
package.json | uni-app官网
#配置环境变量 - vue.config.js | uni-app官网
#环境变量 - Vue2升3指南 | uni-app官网
【报Bug】通过CLI创建的vue3项目微信小程序,调用process.env报错 - DCloud问答
根据官方文档,在package.json定义了自定义环境变量,为什么在代码中获取不到呢,正确的获取方式是什么样的呢 - DCloud问答