Vite 项目配置环境变量和全局变量
因为公司项目有多个环境,而我接手的这个前端项目比较老(前一段时间把项目的构建配置重构了一下,从老版本的 Webpack 换成了 Vite),区分不同环境也是直接用 window.location.host 等域名信息判断。我个人是觉得这样子不太好,还是通过设置不同的 mode,在 CICD 构建阶段来加载不同的环境变量比较好。
使用 .env 等同类型文件配置环境变量
1. 大致配置流程
这里只简单写一下大致流程,这篇文章主要还是用来记录遇到的问题,详细内容可以到官方文档-Env Variables and Modes查看~
Vite 使用dotenv在你的环境目录(environment directory)下加载环境变量文件:
.env # 在所有情况下都会加载
.env.local # 在所有情况下都会加载,一般用来在本地开发时存敏感信息,比如 token 等,所以需要在 .gitignore 里添加它来避免上传暴露敏感信息
.env.[mode] # 只会在特定的mode下加载
.env.[mode].local # 只会在特定的mode下加载,同上需要在 git 中忽视
变量例子如下,默认的变量前缀是VITE_,当然也可以通过改变envPrefix来改变前缀。
VITE_SOME_KEY=123
然后就可以在代码中使用变量啦
console.log(import.meta.env.VITE_SOME_KEY); // 123
2. 遇到的问题:配置完后,任何.env 文件中的环境变量都没有正常的被加载
当我配置完之后,发现 log 出来的是 undefined。检查了一下配置,发现原因是我在 vite.config.js 中配置了 root 配置选项。
我们前面曾提到:Vite 会在你的环境目录(environment directory)下加载环境变量文件。
我们可以看到,环境目录envDir的默认值是 root。而 root 的默认值是process.cwd()。process.cwd()方法会返回 Node.js 进程的当前工作目录。所以正常在没有修改root的情况下,是不用修改 envDir 的。
好巧不巧,老项目的目录结构有点特殊,之前从 Webpack 换成 Vite 的过程中,配置了一下root: "app",但我忘了!!!
所以最终只需要用 envDir 将路径配置正确就好啦。我这里是envDir: "../",仅供参考,具体项目具体配置。
参考配置如下:
export default defineConfig(({ command, mode }) => ({
root: "app",
// Relative to the root
envDir: "../",
build: {
// Relative to the root
outDir: "../dist",
},
// ...
}));
在 Vite 中定义全局变量
1. 大致配置流程
因为之前在 React 源码中看到定义了一个全局变量__DEV__来表示是否处于开发模式,这样就可以区分一些开发模式的逻辑。
在项目的开发中,也会存在有些代码逻辑只需要在本地开发的时候运行,比如在请求头上带上.env.local中拿出来的 token,用来跳过登录,调试线上接口(不知道这样好不好,如果有其他的方案可以在评论区发出来一起学习交流一下,感谢~)。所以,我也参照 React 源码中的方式,定义了一个全局变量__DEV__,这时候就要用到 Vite 的 define 配置选项。
参考配置如下:
export default defineConfig(({ command, mode }) => ({
// ...
define: {
__DEV__: mode === "development",
},
// ...
}));
2. 遇到的问题:在其他文件中使用全局变量__DEV__时,eslint 会报no-undef的错误
错误如下:
但是在 React 源码中是没有这个报错的,我本来以为 React 关闭了 no-undef 的规则,但是试了一下并没有。
然后我又在 eslint 配置文件.eslintrc中查找了一下,发现有一个 globals 配置选项,而它就是 eslint 用来标识全局变量的。
第一种方法是可以通过注释标识:
// 默认是只能读不能写
/* global var1, var2, __DEV__ */
// 可以手动改为即可读又可写
/* global var1:writable, var2:writable */
第二种就是在配置文件.eslintrc中配置:
{
// ...
"globals": {
"var1": "writable",
"var2": "readonly",
"__DEV__": "readonly"
}
}
衍生知识点:在 Vite 配置文件中定义全局变量时,如何使用环境变量
在 Vite 的配置文件 vite.config.js 中,默认是不加载 .env 文件中的环境变量的。因为正常情况下,只有在评估完 Vite 配置之后,才知道哪些文件需要被加载,比如之前我们提到的root和envDir都会影响到加载的行为。不管如何,如果想要在配置中加载环境变量,可以使用 loadEnv 去加载环境变量。
参考配置如下,想了解更多可以去官网-environment variables查看~
import { defineConfig, loadEnv } from "vite";
export default defineConfig(({ command, mode }) => {
// Load env file based on `mode` in the current working directory.
// 根据 mode 在当前的工作目录中加载 env 文件
// Set the third parameter to '' to load all env regardless of the `VITE_` prefix.
// 第三个参数是设置要加载的环境变量的 prefix 前缀,当设为'',在加载环境变量时就会不在意前缀,全部加载。
const env = loadEnv(mode, process.cwd(), "");
return {
// vite config
define: {
__APP_ENV__: env.APP_ENV,
},
};
});