工程项目中.env 文件原理

概述

目前的工程化前端项目中,不可缺少需要配置环境相关信息,根据环境区分,使用什么变量内容等。 .env 文件在我们项目中非常常见,在 vue-cli 、 create-react-app 、vite+vue中都有使用。

核心库

dotenv

dotenv 的作用

Dotenv 是一个零依赖模块,可将 .env 文件中的环境变量加载到 process.env 中。

如果需要使用变量,则配合如下扩展包使用dotenv-expand。

.env 文件写法:

js 复制代码
NAME=dawei
AGE=18
VITE_APP_ENV=production
VITE_ROUTER_BASE_URL=/ai-form

单从这个文件来看,我们可以知道有如下功能需要实现:

  1. 读取 .env 文件
  2. 解析 .env 文件拆成键值对的对象形式
  3. 赋值到 process.env 上
  4. 最后返回解析后得到的对象

简单实现

js 复制代码
const fs = require('fs');
const path = require('path');

const parse = function parse(src){
  const obj = {};
  // 用换行符 分割
  // 比如
  /**
     * NAME=若川
     * AGE=18
     * BLOG=https://xx.gitee.io
    */
  src.toString().split('\n').forEach(function(line, index){
    // 用等号分割
    const keyValueArr = line.split('=');
    // NAME
    key = keyValueArr[0];
    // 若川
    val = keyValueArr[1] || '';
    obj[key] = val;
  });
  // { NAME: '若川', ... }
  return obj;
}

const config = function(){
  // 读取 node 执行的当前路径下的 .env 文件
  let dotenvPath = path.resolve(process.cwd(), '.env');
  // 按 utf-8 解析文件,得到对象
  // { NAME: '若川', ... }
  const parsed = parse(fs.readFileSync(dotenvPath, 'utf-8'));

  // 键值对形式赋值到 process.env 变量上,原先存在的不赋值
  Object.keys(parsed).forEach(function(key){
    if(!Object.prototype.hasOwnProperty.call(process.env, key)){
      process.env[key] = parsed[key];
    }
  });

  // 返回对象
  return parsed;
};

console.log(config());
console.log(process.env);

// 导出 config parse 函数
module.exports.config = config;
module.exports.parse = parse;

简版的 config 函数还缺失挺多功能,比如:

可由用户自定义路径

可由用户自定义解析编码规则

添加 debug 模式

完善报错输出,用户写的 env 文件自由度比较大,所以需要容错机制。

优化

js 复制代码
function resolveHome (envPath) {
    return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath
}

const config = function(options){
    // 读取 node 执行的当前路径下的 .env 文件
    let dotenvPath = path.resolve(process.cwd(), '.env');
    // utf8
    let encoding = 'utf8';
    // debug 模式,输出提示等信息
    let debug = false;
    // 对象
    if (options) {
        if (options.path != null) {
            // 解析路径
            dotenvPath = resolveHome(options.path)
        }
        // 使用配置的编码方式
        if (options.encoding != null) {
            encoding = options.encoding
        }
        // 有配置就设置为 true
        if (options.debug != null) {
            debug = true
        }
    }

    try {
        // 按 utf-8 解析文件,得到对象
        // { NAME: '若川', ... }
        // debug 传递给 parse 函数 便于
        const parsed = parse(fs.readFileSync(dotenvPath, { encoding }), { debug });

        // 键值对形式赋值到 process.env 变量上,原先存在的不赋值
        Object.keys(parsed).forEach(function(key){
            if(!Object.prototype.hasOwnProperty.call(process.env, key)){
                process.env[key] = parsed[key];
            } else if (debug) {
                console.log(`"${key}" is already defined in \`process.env\` and will not be overwritten`);
            }
        });

        // 返回对象
        return parsed;
    }
    catch (e) {
        return { error: e };
    }
};

总结

dotenv 源码中,parse 函数主要是一些正则和单双引号、跨平台等细致处理。

一句话总结 dotenv 库的原理。用 fs.readFileSync 读取 .env 文件,并解析文件为键值对形式的对象,将最终结果对象遍历赋值到 process.env 上。

dotenv 把环境变量加载进 process.env 对于前端项目来说还不够,因为浏览器环境是访问不到 process 的,需要通过 webpack 的 DefinePlugin 在构建阶段把变量替换为对应的值

相关推荐
用户11795365478几秒前
企业团队编程软件怎么选:AI编程工具的协作与落地能力对比
javascript
believed_breadfruit6 分钟前
我开源了一个HTML 分页导出工具,解决了复杂页面的内容截断、跨页错乱和长文档白屏问题
前端·javascript·github
福狼11 分钟前
从“网墙”到柔性曲面:一次 WebGPU 波浪的逆向分析与重建
前端·逆向
宝哥聊编程18 分钟前
主流 Agent 平台对比:Coze、Dify、飞书、扣子、OpenClaw 落地实操手册
前端·人工智能·飞书
时间的情敌40 分钟前
Vue3 + Cesium 实战:本地上传 GLB 模型、模型上叠加 GLB、点击控制透明度
前端·vue.js·cesium
拖孩44 分钟前
流量主门槛从 500 降到 100,我的小程序上线 18 小时够到了线
前端·后端·微信小程序
深蓝AI1 小时前
编码 Agent 的界面味靠提示词压不住:Impeccable 用无模型规则拦同一套模板
前端·程序员
CCIE-Yasuo1 小时前
网络安全-Javascript基础
javascript·安全·web安全
January12072 小时前
【AI方法笔记】2026-11-02:模型流式吐 JSON 时,前端会遇到四种崩法
前端·人工智能·笔记·json
asdzx672 小时前
C# 操作 PDF 元数据:从属性写入到字段提取的完整流程
前端·pdf·c#