封装dotenv库实现类似Vite加载环境变量的行为

简介: 封装dotenv库实现类似Vite加载环境变量的行为

dotenv的作用


.env文件中的环境变量加载到 process.env


简单使用示例


安装依赖


yarn add dotenv


编写 .env 文件


# 数据库相关内容
DB_USER=test
DB_PWD=123456
DB_PORT=3306


test.js


const dotenv = require('dotenv')
const res = dotenv.config()
console.log(res);
console.log(process.env.DB_PORT);


运行结果


注意.env文件需在项目的根目录中(终端执行指令的目录)


网络异常,图片无法展示
|


Vite中读取.env文件的规则


这里直接贴图原文档内容,不做过多赘述


网络异常,图片无法展示
|


很详细的叙述了Vite加载额外环境变量的规则


循序渐进的实现


一.指定存放环境变量文件

  1. 首先通过process.cwd(),获取终端执行命令的路径


console.log(process.cwd())


网络异常,图片无法展示
|


  1. dotenv.config的参数定义


export interface DotenvConfigOptions {
  /**
   * You may specify a custom path if your file containing environment variables is located elsewhere.
   */
  path?: string;
  /**
   * You may specify the encoding of your file containing environment variables.
   */
  encoding?: string;
  /**
   * You may turn on logging to help debug why certain keys or values are not being set as you expect.
   */
  debug?: boolean;
}


可以看出通过path参数指定环境变量的路径


测试代码如下


const dotenv = require('dotenv')
const baseDir = process.cwd()
const res1 = dotenv.config({path:`${baseDir}/.lalala`})
const res2 = dotenv.config({path:`${baseDir}/.lalala2`})
const res3 = dotenv.config({path:`${baseDir}/.不存在`})
console.log(res1);
console.log(res2);
console.log(res3);
console.log(process.env.TEST_ENV);


输出内容分别如下


{ parsed: { TEST_ENV: 'test1' } }
{ parsed: { TEST_ENV: 'test2' } }
{
  error: 'xxx'
}
test1


可以看出当指定文件存在时,解析的内容会在结果的parsed属性中

不存在时,解析结果只包含错误信息error

当指定了path参数后,执行多个donEnv.config方法,只会自动加载第一个的解析结果到process.env中去


二.加载读取的环境变量


这个步骤简单,直接遍历parsed属性的内容,将其添加到process.env属性上即可


function load(parseEnvObj) {
  const { parsed } = parseEnvObj
  if (parsed && parsed instanceof Object) {
    Object.getOwnPropertyNames(parsed).forEach((k) => {
      process.env[k] = parsed[k]
    })
  }
}


测试


const baseDir = process.cwd()
const res1 = dotenv.config({ path: `${baseDir}/.lalala` })
const res2 = dotenv.config({ path: `${baseDir}/.lalala2` })
const res3 = dotenv.config({ path: `${baseDir}/.不存在` })
load(res1);
load(res2);
load(res3);
console.log(process.env.TEST_ENV); // test2


三.实现Vite的读取规则


function loadEnv() {
    const baseDir = process.cwd()
    // .env
    load(dotenv.config({ path: `${baseDir}/.env` }))
    // .env.local
    load(dotenv.config({ path: `${baseDir}/.env.local` }))
    // .env.[mode]
    load(dotenv.config({ path: `${baseDir}/.env.${process.env.NODE_ENV}` }))
    // .env.[mode].local
    load(dotenv.config({ path: `${baseDir}/.env.${process.env.NODE_ENV}.local` }))
}


简单封装成一个函数,直接调用loadEnv


mode的设置可以通过cross-env库设置,如下所示

package.json


{
    "scripts": {
        "dev": "cross-env NODE_ENV=development node ./tests/test.js",
    },
}


四.限制环境变量前缀


简单修改后的代码,添加了前缀的过滤


function load(parseEnvObj, prefix = '') {
    const { parsed } = parseEnvObj
    if (parsed && parsed instanceof Object) {
        Object.getOwnPropertyNames(parsed).forEach((k) => {
            if (k.indexOf(prefix) === 0) {
                process.env[k] = parsed[k]
            }else{
                process.env[k] = undefined
            }
        })
    }
}
function loadEnv(options = {}) {
    const { prefix = '' } = options
    const baseDir = process.cwd()
    // .env
    load(dotenv.config({ path: `${baseDir}/.env` }), prefix)
    // .env.local
    load(dotenv.config({ path: `${baseDir}/.env.local` }), prefix)
    // .env.[mode]
    load(dotenv.config({ path: `${baseDir}/.env.${process.env.NODE_ENV}` }), prefix)
    // .env.[mode].local
    load(dotenv.config({ path: `${baseDir}/.env.${process.env.NODE_ENV}.local` }), prefix)
}


测试


.env内容


# 数据库相关内容
DB_USER=test
DB_PWD=123456
DB_PORT=3306
SUGAR_USER=sugar


loadEnv()
console.log(process.env.DB_USER); // test
console.log(process.env.SUGAR_USER); // sugar


loadEnv({prefix:'SUGAR'})
console.log(process.env.DB_USER); // undefined
console.log(process.env.SUGAR_USER); // sugar


最终版


// 读取配置的环境变量
const dotenv = require('dotenv')
function load(parseEnvObj, prefix = '') {
  const { parsed } = parseEnvObj
  if (parsed && parsed instanceof Object) {
      Object.getOwnPropertyNames(parsed).forEach((k) => {
          if (k.indexOf(prefix) === 0) {
              process.env[k] = parsed[k]
          }else{
              process.env[k] = undefined
          }
      })
  }
}
function loadEnv(options = {}) {
  const { prefix = '' } = options
  const baseDir = process.cwd()
  // .env
  load(dotenv.config({ path: `${baseDir}/.env` }), prefix)
  // .env.local
  load(dotenv.config({ path: `${baseDir}/.env.local` }), prefix)
  // .env.[mode]
  load(dotenv.config({ path: `${baseDir}/.env.${process.env.NODE_ENV}` }), prefix)
  // .env.[mode].local
  load(dotenv.config({ path: `${baseDir}/.env.${process.env.NODE_ENV}.local` }), prefix)
}
module.exports = loadEnv


使用


const loadEnv = require('modulePath')
loadEnv()
// or
loadEnv({prefix:'xx'})


TODO


下一次分享一下Vite中这部分的源码实现逻辑


相关文章
|
JavaScript
源码学习:Vite中加载环境变量(loadEnv)的实现
源码学习:Vite中加载环境变量(loadEnv)的实现
7221 0
|
30天前
|
JavaScript 前端开发 API
vue3中常用插件的使用方法:按需引入自定义组件,自动导入依赖包,自动生成路由,自动生成模拟数据
vue3中常用插件的使用方法:按需引入自定义组件,自动导入依赖包,自动生成路由,自动生成模拟数据
548 0
|
1月前
|
API
Vite 中环境变量的配置方法
【10月更文挑战第10天】 Vite 中环境变量的配置方法
252 2
|
3月前
|
前端开发 开发者
在前端开发中,webpack 作为模块打包工具,其 DefinePlugin 插件可在编译时动态定义全局变量,支持环境变量定义、配置参数动态化及条件编译等功能。
在前端开发中,webpack 作为模块打包工具,其 DefinePlugin 插件可在编译时动态定义全局变量,支持环境变量定义、配置参数动态化及条件编译等功能。本文阐述 DefinePlugin 的原理、用法及案例,包括安装配置、具体示例(如动态加载资源、配置接口地址)和注意事项,帮助开发者更好地利用此插件优化项目。
91 0
|
6月前
|
Perl
如何修改第三方库
如何修改第三方库
50 0
|
6月前
|
JavaScript 测试技术
vue不同环境打包环境变量处理
vue不同环境打包环境变量处理
296 0
|
11月前
|
JavaScript 小程序
VUE3(三十五)vite构建的项目配置使用.env文件
VUE3(三十五)vite构建的项目配置使用.env文件如标题所示:我要在vue3项目使用.env文件。 先介绍一下项目背景,项目使用VUE3.2 + vite2.9 + typescript搭建。 我基本断定,vue3使用.env文件的方法可能和vue2使用.env文件的方法可能是不同,关于vue2项目如何使用.env文件,请移步《VUE2(七)VUE配置env文件使用》
386 1
|
JSON 小程序 前端开发
小程序引入第三方插件Vant和小程序WeUl组件库
现如今前端的技术再向框架化的发展,框架的使用提高我们的编码的效率和性能的优化,同样CSS样式也是越来越高的要求,今天我要向大家介绍的就是较火的前端UI框架Vant UI组件库
268 0
|
JavaScript 安全 前端开发
vue打包以后,如何配置文件修改全局接口地址
vue打包以后,如何配置文件修改全局接口地址
vue打包以后,如何配置文件修改全局接口地址
|
JavaScript
使用Vue脚手架Vue-cli快速搭建过程,生成目录文件功能解析(全局安装和局部安装)
关于vue的脚手架,大家应该都比较熟悉,使用它可以快速的生成vue项目框架让我们进行开发,一般安装脚手架有全局和局部安装两种,如果考虑到经常开发的项目脚手架版本不同,那么更推荐使用局部安装。
335 0
使用Vue脚手架Vue-cli快速搭建过程,生成目录文件功能解析(全局安装和局部安装)