每日鸡汤:每个你想要学习的瞬间都是未来的你向自己求救
假设你有一个项目,后端提供两个接口请求的地址,分别是
正式环境:https://web.com/api
测试环境:https://web-test.com/api
本地开发用localhost:3000测试,使用process.env.NODE_ENV === 'development' 来判断是否是测试环境,完全没有问题。此时你可以这样写
// env.ts
// 正式环境地址
const proUrl = 'https://web.com/api'
// 测试环境地址
const devUrl= 'https://web-test.com/api'
const isTest = process.env.NODE_ENV === 'development'
// 真正的请求地址
export const realReqUrl = isTest ? devUrl : proUrl
但是当你提测的时候总不能把自己电脑的 ip 地址发给测试同事吧,所以你需要和上线之后一样,部署到一个域名上,只不过这个域名需要访问测试环境的接口地址,也就是devUrl
1. 线上的域名【需要使用 proUrl 接口】
https://myweb.com
2. 测试环境的域名【需要使用 devUrl 接口】
https://myweb-test.com
在开发完成后,第一步是部署 https://myweb-test.com 这个域名,给内部员工测试,测试通过之后再部署 https://myweb.com 域名给全世界用户看
问题出在测试环境域名部署这一步骤,因为nuxt3的部署命令如下
npm run generate
npm run preview
在运行第一个命令 generate 之后,process.env.NODE_ENV 这个环境变量就会变成 production 但是这不是我们想要的,我们需要 isTest 这个变量保持 true
那就只能再改进一下,已知线上域名和测试域名不同,所以可以想到用域名区分,改进后的代码如下
// env.ts
// 正式环境地址
const proUrl = 'https://web.com/api'
// 测试环境地址
const devUrl= 'https://web-test.com/api'
// const isTest = process.env.NODE_ENV === 'development'
let isTest = process.env.NODE_ENV === 'development'
// 注意一定要判断!process.server,否则会报错【location is not defined】
if (!process.server) {
// 如果当前的host 是 myweb-test.com 那么isTest就设为ture
isTest = isTest || ['myweb-test.com'].includes(location.host) || false
}
// 真正的请求地址
export const realReqUrl = isTest ? devUrl : proUrl
你以为这样看起来很完美了么?错!
对于一般的非服务端渲染的框架,比如vite的基础框架,这样就可以了,但是nuxt3之类的服务端框架,和vue普通的框架部署有一些区别,因为它有些运行在服务端的方法比如【useAsyncData】
运行在服务端的方法,我们也要正确的判断使用 proUrl 还是devUrl,要不然就悲剧了
比如我们在某个页面中使用 useAsyncData 中请求了一个接口,但是此时就不会走 !process.server 这个条件,同时process.env.NODE_ENV === 'development' 的值为false。就会在useAsyncData中请求 proURL 所以就完蛋了。
除非你能保证,整个项目能永远永远永远不用服务端方法,或者产品经理在催你,然后你确定没有使用服务端的方法,可以临这么部署,不过,有很大的风险,你的 bug 肯定会在某一次迭代的时候让你摸不到头脑。
并且相信我在nuxt.config.ts中增加 ssr: false 试图不在服务端运行任何函数是没有用处的,即便几设置了,然后使用了useAsyncData方法,useAsyncData方法也依旧会执行
所以我们还需要改进一下,增加关于服务端的判断,请看下面代码
// env.ts
// 正式环境地址
const proUrl = 'https://web.com/api'
// 测试环境地址
const devUrl= 'https://web-test.com/api'
// const isTest = process.env.NODE_ENV === 'development'
let isTest = process.env.NODE_ENV === 'development'
// 注意一定要判断!process.server,否则会报错【location is not defined】
if (!process.server) {
// 如果当前的host 是 myweb-test.com 那么isTest就设为ture
isTest = isTest || ['myweb-test.com'].includes(location.host) || false
} else {
// 判断服务端的环境变量中的IS_DEV是否为TRUE
isTest = isTest || process.env.IS_DEV === 'TRUE' || false
}
// 真正的请求地址
export const realReqUrl = isTest ? devUrl : proUrl
问题又来了,环境变量中拿来的 IS_DEV 啊???那肯定是需要你手动增加的!!
怎么增加,你不会傻傻的去 nuxt3 官网查了吧,然后又是让你配置 .env 文件,然后又是在nuxt.config.ts 中配置 runtimeConfig。 别查了没有用,不管你怎么配置都是一套代码,无法解决我们的问题。
根据官网在 env 文件里增加的环境变量,唯一的好处就是可以使用 process.env.xx 获取到,但是这和我们在普通的 ts 文件中写一个普通的常量导出,然后在使用的时候导入,效果是差不多的。
至少我遇到的项目没有手动配置到 env 文件,也可以满足我的需求。
正确的解决办法是,在部署过程中和架构组同事商量,在你部署的node服务中,增加一个名为IS_DEV 值为 TRUE 的环境变量,恕我直言,我也没搞懂咋弄的,我就是改了一下架构组给我们的上线配置文件中的一个地方文件就行了。记住有一点就是别折腾咱们的代码了!