源码浅析——vite是如何读取.env文件的

130 阅读2分钟

.env 文件

官网说明 环境变量和模式 | Vite 官方中文文档 (vitejs.dev)

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 方法

image.png

image.png

config.ts

获取加载 .env 文件的地址 -- 如果传入的有指定 env 地址,则从指定地址获取,如果没有从根目录下获取。得到调用路径地址后,调用 env.ts 的 loadEnv 获取文件内容

image.png

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);