背景
在前端工程化盛行之时,环境变量的概念悄然进入了前端的视野。在远古时代的前端开发中,没有工程化的概念,开发环境、测试环境、生产环境都需要手动配置。然而,随着现代打包工具如 webpack、snowpack、rollup 等的流行,我们不得不开始重视起环境变量的作用。
在现代前端开发的整个链路中,环境变量扮演着项目配置的枢纽角色。在旧的项目中,或许并没有采用现代化的环境变量管理方式,而是通过手动创建多个环境配置文件(如 config/dev.env.js、config/prod.env.js)来设置环境变量。虽然这种方式能够满足基本需求,但不够灵活和方便,需要手动维护多个配置文件,难以自动切换。所有这就有了使用.env.development
、.env.production
、.env.test
来帮助我们管理环境变量的方式。
如何使用?
- 通常我们会在项目的根目录下新建3个文件,分别为
.env.development
、.env.production
、.env.test
注意文件是只有后缀的。
- 然后在每个文件内分别写上我们对应的,我们所匹配的模式和需要请求的API即可
js
//依赖vite打包项目的写法
VITE_BASE_MODE = development/production/test:
VITE_BASE_URL = 'API'//我们对应的API
//依赖webpacl打包项目的写法
VUE_APP_API_URL=https://api.a.com
3.我们需要修改我们的package.json文件
js
"scripts": {
"dev": "vue-cli-service serve",
"test": "vue-cli-service serve --mode test",
"build": "vue-cli-service build",
"build:test": "vue-cli-service build --mode test",
"lint": "vue-cli-service lint"
},
4.在我们的网络请求文件中使用,
vite
在项目中,如果我们使用的是 vite ,要想在项目中使用变量的开头就需要是 VITE_,而不是 VITE_ 开头的变量就不能被获取到。
js
// 在 vite 程序中获取
console.log(import.meta.env.VITE_APP_BASE_API); // /dev-api
// 在 vue2 项目中获取
console.log(process.env.VUE_APP_BASE_API); // /vite
console.log(process.env.VUE_APP_API_URL) //wepback
注意 : 通常Vite 默认是不加载 .env
文件的,因为这些文件需要在执行完 Vite 配置后才能确定加载哪一个,不过当我们的确需要时,我们可以使用 Vite 导出的 loadEnv
函数来加载指定的 .env
文件。所以我们需要在vite.config.js
文件中进行下面的配置。
javascript
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ command, mode }) => {
// 根据当前工作目录中的 `mode` 加载 .env 文件
// 如果当前环境是开发环境,则 mode 为 development
// 设置第三个参数为 '' 来加载所有环境变量,而不管是否有 `VITE_` 前缀。
const env = loadEnv(mode, process.cwd(), '')
const { VITE_APP_BASE_API } = env // VITE_APP_BASE_API = /dev-api
return {
// vite 配置
define: {
__APP_ENV__: JSON.stringify(env.APP_ENV),
},
}
})
原理
讲到原理我们先来看一下process
和process.env
的官方解释:
- process
process
对象是一个global
(全局变量),提供有关信息,控制当前 Node.js 进程。作为一个对象,它对于 Node.js 应用程序始终是可用的,故无需使用require()
。
- process.env
process.env
属性返回一个包含用户环境信息的对象。在node环境中,当我们打印
process.env
时,发现它并没有NODE_ENV
这一个属性。实际上,process.env.NODE_ENV
是在package.json的scripts
命令中注入的,也就是NODE_ENV
并不是node自带的,而是由用户定义的,至于为什么叫NODE_ENV
,应该是约定成俗的吧。
其实环境变量运行的背后是一系列工具链( dotenv
+ cross-env
+ webpack DefinePlugin
)相互作用的成果
dotenv
dotenv
是一个 Node.js 模块,它的作用是从一个 .env 文件中加载环境变量到 Node.js 的 process.env 对象中。注意:如果.evn文件中存在与系统中相同的环境变量, 那么将跳过该变量的加载。
dotenv的作用是为了方便将大量的将.env文件所有的key-value赋值增加到process.env上面去
cross-env
cross-env
是一个 Node.js 包,它的作用是为跨平台的运行命令设置环境变量。它解决了不同操作系统下设置环境变量的差异性问题。
cross-env 是为了兼容 package中script的命令行是需要考虑在不同系统中的不同写法 NODE_ENV='production' 在windows必须写成set NODE_ENV="production"
DefinePlugin
DefinePlugin
是 webpack 中的一个插件,它的作用是定义全局的常量,这些常量在编译过程中会被替换为实际的值。它常被用于在编译时将环境变量注入到代码中
DefinePlugin 可以将变量暴露在整个项目中,方便在前端项目中调用,webpack在构建(编译)过程中直接替换掉 ,相当于c中预定义定义的常量
在这三者的配合下,完成了对前端环境变量的管理