Vite 项目配置环境变量和全局变量

10,158 阅读4分钟

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)下加载环境变量文件。

image.png

image.png

我们可以看到,环境目录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的错误

错误如下:

image.png

但是在 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 配置之后,才知道哪些文件需要被加载,比如之前我们提到的rootenvDir都会影响到加载的行为。不管如何,如果想要在配置中加载环境变量,可以使用 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,
    },
  };
});