环境变量就是会根据当前的代码环境变化的变量叫做环境变量。
我们在项目中的代码环境大致分为下面几种:
1、开发环境
2、测试环境
3、预发布环境
4、灰度环境
5、生产环境
我们在项目中通常需要区分线上环境和开发环境的后端地址,例如:
开发环境:http://dev.api/
生产环境:https://api/
我们每次在开发的时候都要区分confug.url
的地址,如果测试的时候忘改地址了,地址是线上地址,那就会出大问题,测试数据直接影响到线上了。
我们在使用一些第三方sdk
:百度地图sdk
、小程序sdk
等第三方sdk
接口的时,需要带上身份信息APP_KEY
,测试环境、生产环境、开发环境是不一样的key
,例如这里的三种开发环境对应的不同sdk
:
110
111
112
假设现在是开发环境,APP_KEY为110
,这里模拟一个axios
请求:
// request.js
const getUserInfo = () => {
axios.post({
params : {
APP_KEY : 110 // 开发环境的APP_KEY : 110
}
})
}
如果我们切换到生产环境,这里的APP_KEY
需要换成112
,如果切到测试环境,APP_KEY
要换成111
,这种手动更换是非常麻烦的。
所以我们这里需要区分一下生产环境和开发环境
新建两个文件:
.env.development
开发和测试环境
.env.production
生产环境
// .env.development
APP_KEY = 110
BASE_URL = http://test.api/
// .env.production
APP_KEY = 112
BASE_URL = http://api/
我们在运行npm run dev
的时候,希望上面的asiox
的请求读的是.env.development
文件中的APP_KEY
,运行npm run build
的时候,希望asiox
的请求读的是.env.production
中的APP_KEY
,并且对应的axios.basu_url
自动更换到对应的地址。(这就是环境变量的意义)
在vite
中环境变量的处理:dotenv
第三方库(vite
内置了dotenv
库)
dotenv
第三方库会在启动npm run dev
的时候读取.env
文件,并解析这个文件中的环境变量,将其注入到process
对象上。
在node.js中,process对象(进程对象)代表node.js应用程序。
process 对象是一个全局变量,它提供当前 Node.js 进程的有关信息,以及控制当前 Node.js 进程。
process文档 (点击直达)
export default defineConfig(({command})=>{
console.log('process内容',process.env);
// ......其他配置
})
vite
考虑到和其他配置的一些冲突问题,它不会直接注入到process
对象下,而是调用vite
的loadEnv
来手动确认env
文件。
loadEnv
的三个参数:
1、mode
:模式,根据你启动的的命令来的,比如npm run dev
就是开发环境,build
就是生产环境,如果你启动的命令为:npm run dev --mode development
,那么mode
会设置为development
传递进来,启动命令为npm run dev
的话系统会默认帮我们自动补全,这里也可以对mode
进行更改,--mode xxxx(自定义名)
2、envDir
:环境变量配置文件所在目录,这里可以使用process.cwd()
,也可以这么写:envDir:"C:\Users\123\Desktop\vite-test"
指向文件目录地址
3、prefixes
:接受的环境变量前缀,不写默认为 env
export default defineConfig(({command,mode})=>{
const env = loadEnv(mode,process.cwd(),prefixes="")
console.log(env); // 这里APP_KEY 110,并且BASE_URL也对应的是测试环境地址,挂载到env下面
// ......其他配置
})
process.cwd():返回当前node进程的工作目录
当我们调用loadEnv
的时候,它会做如下几件事情:
1、直接找到.env
文件,并解析其中的环境变量,放到一个对象里
2、将传进来的mode
这个变量的值进行拼接:.env.development
,并根据提供的目录去取对应的配置文件进行解析,并放进一个对象里
3、我们可以理解为下面的操作:
const baseEnvConfig
= 读取.env
的配置
const modeEnvConfig
= 读取.env.mode
(根据传入的mode
决定,mode=development
那么就是.env.development
)文件
const lastEnvConfig
= {...baseEnvConfig,...modeEnvConfig}
如果是客户端,vite
会将对应的环境变量注入到import.meta.env
里面去。
但是这里vite
做了一个拦截,为了防止我们将隐私性的变量直接注入到import.meta.env
,我们的环境变量就必须得是VITE_
开头,否则vite
不会将环境变量注入到import.meta.env
// .env.development文件:开发环境
APP_KEY = 110
BASE_URL = http://dev.api/
// request.js
console.log('import.meta.env的内容',import.meta.env)
未找到.env.development
文件中的环境变量,因为开头不是VITE_
,vite
拦截了注入操作。
// .env.development文件:开发环境
VITE_APP_KEY = 110
VITE_BASE_URL = http://dev.api/
当然,VITE_
是一个默认前缀,我们也可以在vite.base.config.js
文件中更改import.meta.env
注入的默认前缀:
import { defineConfig } from "vite";
export default defineConfig({
envPrefix:"ABC_" // 配置import.meta.env注入的前缀名称
})
到这里环境变量配置就已经完成了,如果我们想要添加新的环境,例如:测试环境,那么只需要新建一个.env.test
文件
// .env.test文件:测试环境
ABC_APP_KEY = 111
ABC_BASE_URL = http://test.api/
在package.json
中添加测试环境的启动方式"test" : "vite --mode test"
{
"scripts": {
"dev": "vite",
"build" : "vite build",
"test" : "vite --mode test"
},
// ......其它配置
}
启动npm run test
,loadEnv
会自动根据--mode test
来寻找环境变量文件,.env
后拼接test
,也就是.env.test
文件
// request.js
console.log('import.meta.env的内容',import.meta.env)
// 利用配置的环境变量请求
const getUserInfo = () => {
axios.post({
params : {
APP_KEY : import.meta.env.ENV_APP_KEY // 根据环境变量自动匹配APP_KEY
}
})
}