什么是环境变量
会根据当前的代码环境 产生值的变换的变量 就叫做 环境变量。
简单来说,一个名为 APP_NAME 的变量,
在开发环境下,我们希望它的值是 ”测试的名称“;
在正式环境下,我们希望它的值是 ”正式的名称“。
这个变量我们通过配置文件的方式,使它在运行时自动读取不同的值,而代码中可以正常的使用该变量,不需要做修改。
补充知识1 : process 是什么
process 是node的关于当前进程的一个对象。
这个process对象在存储和读取环境变量的时候就会用到这个属性。
补充知识2 : process.cwd()是什么
process.cwd() 是 当前 node 执行的工作目录。
比如 :
运行项目时 是在 【D:\xxx\study-vite】 下执行的 "npm run dev" 命令,
那么 process.cwd() 的返回值就是 【D:\xxx\study-vite】
当我们在读取环境变量的配置文件的时候会用到这个。
vite 中的环境变量的处理思路(了解)
vite 使用了 dotenv 这个第三方的库,对环境变量进行处理。
dotenv 会自动读取 【.env】这个文件,并解析这个文件中对应的环境变量,将其注入到process对象下;
但是,vite考虑到和其他配置的冲突问题,它不会直接注入到process对象下。
看上去这两句话是互相矛盾的,一个能注入到process下,一个又不会注入进去,那么如何理解上面两句话呢?
这个就涉及到了vite.config.js的一些配置:
1、【envDir】 : 用来配置当前环境变量的文件地址,默认是 .env 文件,但是可以通过 envDir 这个配置进行修改配置文件的目录。
1.代码会读取环境变量
2.但是,由于我们的环境配置文件的加载是在最后的,所以极有可能会将 envDir 进行修改,此时,后面的环境变量就会有可能将前面的覆盖掉,这样第一步读取的环境变量就无效了。
【关于vite.config.js相关的内容,可以参考这篇文章 :https://blog.csdn.net/qq_39505245/article/details/134332060】
【此处看上去有些晦涩难懂,如果阅读起来有些难,可以跳过,对实际操作并没有影响,只是为了介绍一些配置的简单过程】
2、vite 针对【1】中的环境变量会被覆盖的问题,给出了解决方案 :
使用 vite 的 loadEnv 来手动确认 .env 文件。
通过这种直接指定的方式,就避免了变量覆盖的问题。
通过以上两个步骤的解读,就形成了以下结论 :
环境变量仍然会注入到 process 对象中,但是需要使用 vite提供的 loadEnv 这个工具来明确读取环境变量。
这样就很好的解决了这两句话的矛盾。
环境变量的配置文件命名
.env : 所有环境都用到的环境变量
.env.development : 开发环境用到的环境变量
(默认情况下,vite将我们的开发环境取名为development)
.env.production : 生产环境用到的环境变量
(默认情况下,vite将我们的生产环境取名为production)
vite.config.js 中的 mode 的理解
在 vite.config.js 中 有一个参数是 mode,这个参数 就是指定要使用的环境变量的配置文件,默认值是 development
import { defineConfig } from "vite" export default defineConfig(({command,mode})=>{ console.log("mode : ",mode) })
问 : 这个mode 的值是什么呢?它是怎么来的呢?
答: mode 的值是 根据执行命令的脚本来的。
package.json 中的脚本配置如下:"scripts": { "dev1": "vite", "dev2": "vite --mode development", "prod1": "vite build", "prod1": "vite build --mode production", "test":"vite --mode test" },
运行时 :
npm run dev1 ----> vite
npm run dev2 —> vite --mode development
这两个是一样的,因为vite 默认的参数就是 --mode development
同理,对于prod1 和prod2 是一样的【vite.config.js 中的mode 的值 就来自于 执行时命令 --mode 后面的参数】
vite中读取环境变量的过程
核心 : const env = loadEnv(mode,process.cwd(),"xxx")
过程:
1、读取.env 中的变量,因为这个是全局的嘛,首先读这个;
2、根据mode的值,进行环境配置文件的名称拼接,
拼接规则是 :.env.+mode的值,
例如1 :mode的值是 development ,则文件名为 【.env.development】
例如2 :mode的值是 test,则文件名为 【.env.test】
3、将第二个参数【process.cwd()】和完整的环境配置文件的名称进行拼接,去读取环境变量配置文件;
4、如果第一步和第三步两个配置文件有相同的key,则第三步的会覆盖第一步的环境变量的值,即后面的会覆盖前面的。
环境变量的命名规则
这一条很关键!这一条很关键!这一条很关键!
环境变量的配置文件的key,推荐用【全大写字母+下划线】的命名规则。
环境变量的配置文件的key,推荐用【全大写字母+下划线】的命名规则。
环境变量的配置文件的key,推荐用【全大写字母+下划线】的命名规则。
环境变量的使用过程
vite会将环境变量注入到 import.meta.env 这个对象中去;
但是,vite 在考虑到安全性时,为了防止开发者将隐私性的环境变量直接注入到 import.meta.env 中去,做了一层拦截 :
如果你的环境变量不是以 VITE 开头的,则不会被注入;
因此,在编写环境变量的时候,需要以 VITE为前缀!!!
但是,如果你想修改这个前缀,可以使用 envPrefix配置进行修改,这个属性是在vite.config.js环境文件中进行配置。
但是一般不推荐修改。
修改方式如下:
import { defineConfig } from "vite"
export default defineConfig({
envPrefix:"TEST"
})
补充一个小知识(了解):
为什么vite.config.js 可以书写esmodule 的形式
这是因为vite在读取vite.config.js的时候会率先用node去解析文件语法
如果发现你是esmodule规范,会直接将你的esmodule规范进行替换,换成commonjs规范
环境变量的使用案例
本案例是对上面的理论知识的一个实践。
项目目录结构
study-vite
| -- environment # 环境的配置文件
| -- vite.base.config.js # 基础公用的环境配置
| -- vite.dev.config.js # 开发环境配置
| -- vite.prod.config.js # 生产环境配置
| -- node_modules # 项目依赖的目录
| -- .env # 基础公用的环境变量
| -- .env.development # 开发环境的环境变量
| -- .env.production # 生产环境的环境变量
| -- index.html # 主页面
| -- main.js # 主要的js
| -- package.json # 不解释
| -- vite.config.js # vite 的主配置,会加载 environment 目录下的不同配置文件
环境变量的配置文件
.env
# 定义一个全局的变量,无论是哪个环境下都可以使用 VITE_A = 全局的一个变量
.env.development
# 开发环境下使用的变量 VITE_APPNAME = 测试的应用名称
.env.production
# 生产环境用到的变量 VITE_APPNAME = 正式的应用名称
vite的配置文件
vite.base.config.js
// 基础环境配置,目前来讲还没有配置任何的内容 import { defineConfig } from "vite" console.log('load base-config...') export default defineConfig({ })
vite.dev.config.js
// 开发环境的配置,目前来讲还没有配置任何的内容 import { defineConfig } from "vite" console.log('load dev-config...') export default defineConfig({ })
vite.prod.config.js
// 生产环境的配置,目前来讲还没有配置任何的内容 import { defineConfig } from "vite" console.log('load prod-config...') export default defineConfig({ })
vite.config.js
// 主要的vite的配置文件 import { defineConfig } from "vite" // 读取环境变量的 { loadEnv } from "vite" // 引入三个环境配置文件 import ViteBaseConfig from "./environment/vite.base.config" import ViteProdConfig from "./environment/vite.prod.config" import ViteDevConfig from "./environment/vite.dev.config" // 策略模式做一个动态的配置 const envResolver = { "build":()=>{ console.log("生产环境") // 解构的语法 return ({...ViteBaseConfig,...ViteProdConfig}) }, "serve":()=>{ console.log("开发环境") // 另一种写法 return Object.assign({},ViteBaseConfig,ViteDevConfig) } } // 根据 参数 command 的值,使用不同的环境配置文件 export default defineConfig(({command,mode})=>{ console.log("command : ",command) // 指定读取的环境变量的文件 // 第一个参数 : mode // 第二个参数 :文件的目录,自己指定,不一定是 process.cwd() // 第三个参数 :目前还没有搞明白是干啥的,直接使用空字符串就行 const env = loadEnv(mode,process.cwd(),"") console.log("env : ",env) // 根据不同的环境使用不同的配置文件,注意这个地方的写法,非常的奇特 return envResolver[command]() })
main.js
只干了一个事儿 : 就是读取 环境变量的值
// 使用环境变量
console.log(import.meta.env)
index.html
只干了一个事儿 : 引入main.js,执行一下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
测试一个普通的前端项目
<script type="module" src="./main.js" ></script>
</body>
</html>
package.json中的脚本
这里主要展示一下执行的脚本
"scripts": {
"dev": "vite",
"dev1": "vite --mode production",
"prod": "vite build"
},
运行测试
development 环境
npm run dev
development 环境
npm run dev1