- 本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
- 这是源码共读的第40期,链接:【若川视野 x 源码共读】第40期 | vite 是如何解析用户配置的 .env 的 - 掘金 (juejin.cn)。
.env 文件
NODE_ENV='development'
VITE_APP_BASE_API='/api'
vite在拿到上面的 .env 文件后会将文件中的相关变量转换为 import.meta.env.xxx 供给项目中使用
寻找代码
主要涉及到 cli.ts config.ts env.ts 三个文件
cli.ts
构建 vite 运行的相关命令
一般都是在 serve 和build 才会读取配置文件,所以直接从这两个命令下寻找。serve 下有 createServe 方法的执行,build 命令下有build 方法的执行,从两个方法内部执行的开头我们可以看到都调用了 config.js 下的 resolveConfig 方法
config.ts
获取加载 .env 文件的地址 -- 如果传入的有指定 env 地址,则从指定地址获取,如果没有从根目录下获取。得到调用路径地址后,调用 env.ts 的 loadEnv 获取文件内容
env.ts
读取 .env .env.local .env.mode .env.mode.local 四个文件内容 通过 dotenv 转换成变量,通过 dotenv-expand 进行变量合并
简单实现
const { parse } = require("dotenv");
const { expand } = require("dotenv-expand");
const fs = require("fs");
const path = require("path");
/**
* 获取相关配置
* @param {*} initConfig 初始化的配置对象
* @returns 新的配置对象
*/
function resolveConfig(initConfig = {}) {
const env = loadEnv(getEnvPath(initConfig));
return { env };
}
/**
* 获取 env 的路径
* @param {*} initConfig 初始化的配置对象
* @returns env 路径
*/
function getEnvPath(initConfig) {
return initConfig.envPath || process.cwd();
}
/**
* 获取配置内容
* @param {*} envDir 配置文件存放的文件夹
* @returns 解析配置文件后返回的对象
*/
function loadEnv(envDir) {
// 要解析的文件名称
const envFiles = [".env", ".env.local"];
const parsed = Object.fromEntries(
envFiles.flatMap(file => {
const f = path.join(envDir, file);
if (!fs.existsSync(f)) return [];
return Object.entries(parse(fs.readFileSync(f)));
})
);
// 将解析出来的对象添加到 process.env 中
expand({ parsed });
return parsed;
}
const config = resolveConfig();
console.log(config);