第二十六章-Vite的loadEnv方法

1.说明

代码:

import { loadEnv } from 'vite';

loadEnv('development', process.cwd());

目的:

  • 检查process.cwd()路径下.env.development.local.env.development.env.local.env这四个环境文件。
  • 输出NODE_ENVVITE_开头的键值对。
  • VITE_开头的键值对后面的不会覆盖前面的。
  • NODE_ENV的值后面的覆盖前面的。

这行代码是什么意思,网上很少有解释。直接看源码吧。

参考链接:

2.源码

2.1.带注解前置代码

// ↓加载node的path模块
var path$1 = require('path');
var fs$2 = require('fs');

// ↓传入的如果是一个包含'default'的key的对象,则输出对象的'default'的key对应的value。
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e['default'] : e; }

// ↓结合上面二者
var path__default = /*#__PURE__*/_interopDefaultLegacy(path$1);
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs$2);

// ↓检查dir下是否有formats中的路径,返回有就返回路径或者文件
function lookupFile(dir, formats, pathOnly = false) {
    for (const format of formats) {
        // ↓输出dir和formats连接后的路径
        const fullPath = path__default.join(dir, format);
        // ↓同步的检查该路径是否存在,并且该路径对应的是一个文件
        if (fs__default.existsSync(fullPath) && fs__default.statSync(fullPath).isFile()) {
            // ↓是否只要输出路径,否则输出文件
            return pathOnly ? fullPath : fs__default.readFileSync(fullPath, 'utf-8');
        }
    }
    // ↓上面的路径都不满足输出条件,那么再检查一遍检查传入的dir的目录名
    const parentDir = path__default.dirname(dir);
    if (parentDir !== dir) {
        return lookupFile(parentDir, formats, pathOnly);
    }
}

2.1.带注释代码

// 从传参的root目录下获取
// 按顺序 .env.${mode}.local、.env.${mode}、.env.local、.env这四个环境文件
// 输出文件内配置的对象
function loadEnv(mode, root, prefix = 'VITE_') {
    if (mode === 'local') {
        // ↓如果第一个参数传入'local',就报错:
        // ↓"local "不能用作模式名称,因为它与``.env文件的.local后缀冲突。
        throw new Error(`"local" cannot be used as a mode name because it conflicts with ` +
            `the .local postfix for .env files.`);
    }
    // ↓待输出的环境变量对象
    const env = {};
    // ↓要读取的四个文件名称的字符串数组
    const envFiles = [
        /** mode local file */ `.env.${mode}.local`,
        /** mode file */ `.env.${mode}`,
        /** local file */ `.env.local`,
        /** default file */ `.env`
    ];
    // 检查是否有实际的以VITE_*开头的环境变量。
    
    
    // 这些通常是Node内联提供的env对象,并应优先考虑。
    for (const key in process.env) {
        if (key.startsWith(prefix) && env[key] === undefined) {
            env[key] = process.env[key];
        }
    }
    
    
    for (const file of envFiles) {
        // ↓检查根目录下是否有指定配置文件
        const path = lookupFile(root, [file], true);
        if (path) {
            // ↓以换行为单位输出文件中KEY=VAL格式的到结果对象中
            const parsed = main$2.parse(fs__default.readFileSync(path), {
                debug: !!process.env.DEBUG || undefined
            });
            // ↓让环境变量互相使用,这个方法我没仔细研究。不是很懂
            main$1({
                parsed,
                // ↓防止process.env修改
                ignoreProcessEnv: true
            });
            // 只输出以prefix开头的key
            for (const [key, value] of Object.entries(parsed)) {
                // ↓只有这个key在前面没有加载过才赋值
                if (key.startsWith(prefix) && env[key] === undefined) {
                    env[key] = value;
                }
                else if (key === 'NODE_ENV') {
                    // 在.env文件中覆盖NODE_ENV。
                    process.env.VITE_USER_NODE_ENV = value;
                }
            }
        }
    }
    return env;
}

2.3.前置源代码

var path$1 = require('path');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e['default'] : e; }

var path__default = /*#__PURE__*/_interopDefaultLegacy(path$1);

function lookupFile(dir, formats, pathOnly = false) {
    for (const format of formats) {
        const fullPath = path__default.join(dir, format);
        if (fs__default.existsSync(fullPath) && fs__default.statSync(fullPath).isFile()) {
            return pathOnly ? fullPath : fs__default.readFileSync(fullPath, 'utf-8');
        }
    }
    const parentDir = path__default.dirname(dir);
    if (parentDir !== dir) {
        return lookupFile(parentDir, formats, pathOnly);
    }
}


var config_1 = config;
var parse_1$2 = parse$a;

var main$2 = {
	config: config_1,
	parse: parse_1$2
};

2.2.原代码

function loadEnv(mode, root, prefix = 'VITE_') {
    if (mode === 'local') {
        throw new Error(`"local" cannot be used as a mode name because it conflicts with ` +
            `the .local postfix for .env files.`);
    }
    const env = {};
    const envFiles = [
        /** mode local file */ `.env.${mode}.local`,
        /** mode file */ `.env.${mode}`,
        /** local file */ `.env.local`,
        /** default file */ `.env`
    ];
    // check if there are actual env variables starting with VITE_*
    // these are typically provided inline and should be prioritized
    for (const key in process.env) {
        if (key.startsWith(prefix) && env[key] === undefined) {
            env[key] = process.env[key];
        }
    }
    for (const file of envFiles) {
        const path = lookupFile(root, [file], true);
        if (path) {
            const parsed = main$2.parse(fs__default.readFileSync(path), {
                debug: !!process.env.DEBUG || undefined
            });
            // let environment variables use each other
            main$1({
                parsed,
                // prevent process.env mutation
                ignoreProcessEnv: true
            });
            // only keys that start with prefix are exposed to client
            for (const [key, value] of Object.entries(parsed)) {
                if (key.startsWith(prefix) && env[key] === undefined) {
                    env[key] = value;
                }
                else if (key === 'NODE_ENV') {
                    // NODE_ENV override in .env file
                    process.env.VITE_USER_NODE_ENV = value;
                }
            }
        }
    }
    return env;
}

上一章

第二十五章-Node的process

下一章

第二十七章-Vben中的wrapperEnv方法

# vben  vite 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×