.env
.env
文件是一个用于存储环境变量的文件。在开发和部署应用程序时,经常需要在不同的环境中配置不同的变量,例如 API 地址、数据库连接信息、密钥等。在许多应用程序中,.env
文件通常包含一个或多个键值对,用于存储环境变量。
Vite 中的 .env
文件还可以用于配置构建时的变量
需要注意的是,Vite 中的环境变量必须以 VITE_
前缀开头才能被识别。例如,如果您在 .env
文件中定义了一个名为 API_URL
的变量,它将不会被 Vite 识别。您应该将其命名为 VITE_API_URL
。
此外,需要将 .env
文件放置在项目根目录下,并且只能包含键值对,例如:
VITE_API_URL=https://api.example.com
VITE_GLOB_APP_TITLE =YingSide_Demo
关于.env
文件的规范,在vite官方文档中有具体说明:环境变量和模式
创建.env
相关文件
大多数情况下,我们在项目中创建.env
文件,都会是下面的形式
.env # 所有情况下都会加载
.env.[mode] # 只在指定模式下加载
[mode]
指定的是具体模式,所以,一般对于开发,生产和测试环境,都会指定具体的环境
.env
.env.development
.env.production
.env.test
.env
文件
# 所有环境都会加载
# title
VITE_GLOB_APP_TITLE = YingSide_DEMO
# 本地运行端口号
VITE_PORT = 3000
# 启动时自动打开浏览器
VITE_OPEN = true
.env.development
文件
# 只在开发环境加载
VITE_USER_NODE_ENV = development
# 打包时是否删除 console
VITE_DROP_CONSOLE = true
# 公共基础路径
VITE_PUBLIC_PATH = /
# 开发环境接口地址
VITE_API_URL = /api
# 开发环境跨域代理,可配置多个
VITE_PROXY = [["/api","https://mock.mengxuegu.com/mock/6453b964af3bc37f99a23916"]]
.env.production
文件
# 只在生产环境加载
VITE_USER_NODE_ENV = production
# 公共基础路径
VITE_PUBLIC_PATH = /
# 是否启用 gzip 或 brotli 压缩打包,如果需要多个压缩规则,可以使用 “,” 分隔
# Optional: gzip | brotli | none
VITE_BUILD_COMPRESS = none
# 打包压缩后是否删除源文件
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
# 打包时是否删除 console
VITE_DROP_CONSOLE = true
# 是否启用图片压缩
VITE_USE_IMAGEMIN = true
# 线上环境接口地址
VITE_API_URL = "http://www.yanhongzhi.com"
.env.test
文件
# 测试环境
VITE_USER_NODE_ENV = test
# 公共基础路径
VITE_PUBLIC_PATH = /
# 是否启用 gzip 或 brotli 压缩打包,如果需要多个压缩规则,可以使用 “,” 分隔
# Optional: gzip | brotli | none
VITE_BUILD_COMPRESS = none
# 打包压缩后是否删除源文件
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
# 打包时是否删除 console
VITE_DROP_CONSOLE = true
# 测试环境接口地址
VITE_API_URL = "http://www.yanhongzhi.com"
每个.env
文件无非也就是规定一些环境变量,所以都大同小异。目的也很简单,你可以认为其实就是定义了一些全局变量。根据自己项目的具体需要进行配置即可。
切换环境
不是配置了不同环境的文件吗?怎么确定当前是什么环境?很简单,答案就在package.json
文件中
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
//....
}
默认的npm run dev
和npm run build
就分别对应development
开发环境和production
生成环境。
当然,我们也可以自己进行设置,比如:
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"build:dev": "vue-tsc && vite build --mode development",
"build:test": "vue-tsc && vite build --mode test",
//....
}
加上--mode
就能对环境进行设定(具体详细配置可在官方文档查看)
读取.env
文件内容
在vite项目中读取.env
文件内容非常简单,使用import.meta.env
,就可读取当前环境中加载的.env
文件的内容
但是,在关键的配置文件vite.config.ts
中import.meta.env
是使用不了的,返回undefined
。因为vite.config.ts
文件是在 Vite
服务运行之前被 TypeScript 编译器编译的,而 import.meta.env
变量是在 Vite
服务运行时由 Vite
自动注入到代码中的。
为此,vite专门提供了loadEnv()
函数,
帮我们读取当前环境中env
文件的内容。为此,我们可以将默认生成的vite.config.ts
文件中的内容进行修改
import { defineConfig, loadEnv } from "vite";
import vue from "@vitejs/plugin-vue";
// https://vitejs.dev/config/
export default defineConfig(({ mode, command, ssrBuild }) => {
const root = process.cwd();
const env = loadEnv(mode, root);
console.log(env);
return {
plugins: [vue()],
}
});
首先这里的修改将原本defineConfig
函数中的对象,改成了一个函数,并且解构了参数,得到mode, command, ssrBuild
三个属性值
mode 当前环境模式 command 在 Vite 的 API 中,在开发环境下 command 的值为 serve(在 CLI 中, vite dev 和 vite serve 是 vite 的别名),而在生产环境下为 build ssrBuild 服务器共享处理 SSR 和非 SSR 请求的配置,仍是实验性的
process.cwd()
获得当前项目路径,const env = loadEnv(mode, root)
得到的就是当前环境的env对象。
上面打印env
对象,就可以得到.env
和.env.development
中的内容
{
VITE_GLOB_APP_TITLE: 'YingSide_Demo',
VITE_PORT: '3000',
VITE_OPEN: 'true',
VITE_USER_NODE_ENV: 'test',
VITE_PUBLIC_PATH: '/',
VITE_BUILD_COMPRESS: 'none',
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE: 'false',
VITE_DROP_CONSOLE: 'true',
VITE_API_URL: 'http://www.yanhongzhi.com'
}
函数封装与typescript限定
从上面获取的内容可以看出来,得到的值统统都是字符串,如果希望得到具体的类型,比如'true'就应该是boolean类型的true,我们应该从一开始就进行封装。而且现在我们是TS的程序,在写相关的封装函数前,应该先规定好类型。
global.d.ts
:全局TypeScript的类型声明文件
// /types/global.d.ts
/* Vite */
declare type Recordable<T = any> = Record<string, T>;
declare interface ViteEnv {
VITE_USER_NODE_ENV: "development" | "production" | "test";
VITE_GLOB_APP_TITLE: string;
VITE_PORT: number;
VITE_OPEN: boolean;
VITE_REPORT: boolean;
VITE_BUILD_COMPRESS: "gzip" | "brotli" | "gzip,brotli" | "none";
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE: boolean;
VITE_DROP_CONSOLE: boolean;
VITE_PUBLIC_PATH: string;
VITE_API_URL: string;
VITE_PROXY: [string, string][];
VITE_USE_IMAGEMIN: boolean;
}
对于新手来说,Record
类型应该很少使用,它是一个通用的映射类型,它允许您将一个类型中的每个属性映射到另一个属性类型。 基本语法:
type Record<K extends keyof any, T> = {
[P in K]: T;
};
Record
类型的主要用途是在编写通用代码时,允许您动态地创建具有特定属性名称和类型的对象
type Person = {
name: string;
age: number;
};
type PersonRecord = Record<keyof Person, string>;
// 等价于
type PersonRecord = {
name: string;
age: string;
};
wrapperEnv()
函数 上面const env = loadEnv(mode, root)
这句代码,打印的env所有的值均为字符串,所以,编写这个函数的目的,是为了让数据更加的符合要求。在项目根目录下创建build
文件夹以及getEnv.ts
文件
// /build/getEnv.ts
import path from "path";
export function wrapperEnv(envConf: Recordable): ViteEnv {
const ret: any = {};
for (const envName of Object.keys(envConf)) {
let realName = envConf[envName].replace(/\\n/g, "\n");
realName = realName === "true" ? true : realName === "false" ? false : realName;
if (envName === "VITE_PORT") realName = Number(realName);
if (envName === "VITE_PROXY") {
try {
realName = JSON.parse(realName);
} catch (error) {}
}
ret[envName] = realName;
}
return ret;
}
需要注意的是,直接在项目根目录下创建的文件,默认ts是不识别的,因此,如果我们在其他地方导入(./build/getEnv.ts
)这个路径的时候,ts会报错。这需要我们在tsconfig.json
文件中进行设置
{
"compilerOptions":{
//...省略
"baseUrl": "./",
"paths": {
"@": ["src"],
"@/*": ["src/*"]
}
},
"include": [
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
"src/**/*.vue",
"types/**/*.d.ts",
"types/**/*.ts",
"build/**/*.ts",
"build/**/*.d.ts",
"vite.config.ts"
],
"exclude": ["node_modules", "dist", "**/*.js"]
}
vite项目在创建时,会同时生成
tsconfig.json
和tsconfig.node.json
文件,tsconfig.node.json
文件专门用于Node.js环境的TypeScript配置文件,它定义了用于Node.js应用程序的TypeScript编译器选项。vite项目会优先使用tsconfig.json
中配置,但是有时候,会出现判定问题,比如你的文件中使用了commonjs的模块语法,那么ts解析就会自动的去用tsconfig.node.json
,这会给你的开发造成一定的困扰。解决办法可以很简单的将tsconfig.node.json
文件删除即可。毕竟在前端开发环境也不需要专门使用Node.js环境
最基础的vite.config.ts
配置:
import { resolve } from "path";
import { defineConfig, loadEnv, ConfigEnv, UserConfig } from "vite";
import { wrapperEnv } from "./build/getEnv";
import vue from "@vitejs/plugin-vue";
// https://vitejs.dev/config/
export default defineConfig(({ mode, command, ssrBuild }:ConfigEnv):UserConfig => {
//获取当前项目路径
const root = process.cwd();
//获取当前环境变量
const env = loadEnv(mode, root);
//获取当前环境变量的具体键值对配置
const viteEnv = wrapperEnv(env);
return {
plugins: [vue()],
base: viteEnv.VITE_PUBLIC_PATH,
root,
resolve: {
alias: {
"@": resolve(__dirname, "./src") //设置@别名位置
}
},
}
});