文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

dotenv怎么从.env文件中读取环境变量

2023-07-04 21:17

关注

这篇文章主要讲解了“dotenv怎么从.env文件中读取环境变量”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“dotenv怎么从.env文件中读取环境变量”吧!

引言

dotenv.env文件中读取环境变量,然后将其添加到process.env中。这是一个非常简单的库,但是它在开发中非常有用,因为它允许你在.env文件中存储敏感信息,而不是将其存储在代码中。

现在很多库都支持.env文件,例如create-react-appvue-clinext.js等。

使用

根据READMEdotenv只有两个方法:

const dotenv = require('dotenv')// 读取.env文件并将其添加到process.env中dotenv.config()// 解析一段包含环境变量的字符串或Buffer,返回一个对象const config1 = dotenv.parse('FOO=bar\nBAR=foo')console.log(config1) // { FOO: 'bar', BAR: 'foo' }const buffer = Buffer.from('FOO=bar\nBAR=foo')const config2 = dotenv.parse(buffer)console.log(config2) // { FOO: 'bar', BAR: 'foo' }

可以看到,dotenv的使用非常简单,通常我们只需要调用config方法即可。

还有一种方法是预加载,直接通过node -r dotenv/config来运行脚本,这样就不需要在脚本中引入dotenv了。

源码

源码在lib/main.js中,先来看一下全部的代码:

const fs = require('fs')const path = require('path')const os = require('os')const packageJson = require('../package.json')const version = packageJson.versionconst LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\'|[^'])*'|\s*"(?:\"|[^"])*"|\s*`(?:\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg// Parser src into an Objectfunction parse (src) {  const obj = {}  // Convert buffer to string  let lines = src.toString()  // Convert line breaks to same format  lines = lines.replace(/\r\n?/mg, '\n')  let match  while ((match = LINE.exec(lines)) != null) {    const key = match[1]    // Default undefined or null to empty string    let value = (match[2] || '')    // Remove whitespace    value = value.trim()    // Check if double quoted    const maybeQuote = value[0]    // Remove surrounding quotes    value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2')    // Expand newlines if double quoted    if (maybeQuote === '"') {      value = value.replace(/\n/g, '\n')      value = value.replace(/\r/g, '\r')    }    // Add to object    obj[key] = value  }  return obj}function _log (message) {  console.log(`[dotenv@${version}][DEBUG] ${message}`)}function _resolveHome (envPath) {  return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath}// Populates process.env from .env filefunction config (options) {  let dotenvPath = path.resolve(process.cwd(), '.env')  let encoding = 'utf8'  const debug = Boolean(options && options.debug)  const override = Boolean(options && options.override)  if (options) {    if (options.path != null) {      dotenvPath = _resolveHome(options.path)    }    if (options.encoding != null) {      encoding = options.encoding    }  }  try {    // Specifying an encoding returns a string instead of a buffer    const parsed = DotenvModule.parse(fs.readFileSync(dotenvPath, { encoding }))    Object.keys(parsed).forEach(function (key) {      if (!Object.prototype.hasOwnProperty.call(process.env, key)) {        process.env[key] = parsed[key]      } else {        if (override === true) {          process.env[key] = parsed[key]        }        if (debug) {          if (override === true) {            _log(`"${key}" is already defined in `process.env` and WAS overwritten`)          } else {            _log(`"${key}" is already defined in `process.env` and was NOT overwritten`)          }        }      }    })    return { parsed }  } catch (e) {    if (debug) {      _log(`Failed to load ${dotenvPath} ${e.message}`)    }    return { error: e }  }}const DotenvModule = {  config,  parse}module.exports.config = DotenvModule.configmodule.exports.parse = DotenvModule.parsemodule.exports = DotenvModule

可以看到最后导出的是一个对象,包含了configparse两个方法。

config

config方法的作用是读取.env文件,并将其添加到process.env中。

function config (options) {  let dotenvPath = path.resolve(process.cwd(), '.env')  let encoding = 'utf8'  const debug = Boolean(options && options.debug)  const override = Boolean(options && options.override)}

首先定义了一些变量:

if (options) {  if (options.path != null) {    dotenvPath = _resolveHome(options.path)  }  if (options.encoding != null) {    encoding = options.encoding  }}

然后判断了一下options是否存在,如果存在的话,就会根据options的值来修改dotenvPathencoding的值。

const parsed = DotenvModule.parse(fs.readFileSync(dotenvPath, { encoding }))

然后是调用parse方法来解析.env文件,parse方法的实现在下面会讲到。

这里是只用fs.readFileSync来读取.env文件,然后将其传入parse方法中,接着往下:

Object.keys(parsed).forEach(function (key) {    if (!Object.prototype.hasOwnProperty.call(process.env, key)) {        process.env[key] = parsed[key]    } else {        if (override === true) {            process.env[key] = parsed[key]        }        if (debug) {            if (override === true) {                _log(`"${key}" is already defined in `process.env` and WAS overwritten`)            } else {                _log(`"${key}" is already defined in `process.env` and was NOT overwritten`)            }        }    }})

这里是遍历parsed对象,然后将其添加到process.env中,如果process.env中已经存在了该环境变量,那么就会根据override的值来决定是否覆盖。

debug的值表示是否开启调试模式,如果开启了调试模式,那么就会打印一些日志。

最后就是直接返回parsed对象。

parse

parse方法的作用是解析.env文件,将其转换为一个对象。

const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\'|[^'])*'|\s*"(?:\"|[^"])*"|\s*`(?:\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mgfunction parse (src) {  const obj = {}  // Convert buffer to string  let lines = src.toString()  // Convert line breaks to same format  lines = lines.replace(/\r\n?/mg, '\n')  let match  while ((match = LINE.exec(lines)) != null) {    const key = match[1]    // Default undefined or null to empty string    let value = (match[2] || '')    // Remove whitespace    value = value.trim()    // Check if double quoted    const maybeQuote = value[0]    // Remove surrounding quotes    value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2')    // Expand newlines if double quoted    if (maybeQuote === '"') {      value = value.replace(/\n/g, '\n')      value = value.replace(/\r/g, '\r')    }    // Add to object    obj[key] = value  }  return obj}

首先定义了一个正则表达式LINE,用来匹配.env文件中的每一行。

然后是将src转换为字符串,然后将换行符统一为\n

接着就是核心,通过正则表达式的特性通过while循环来匹配每一行。

这个正则着实有点复杂,我是正则渣渣,可以在regex101查看一下。

dotenv怎么从.env文件中读取环境变量

这个正则上面标出了三种颜色,和下面的匹配的值的颜色相互对应,然后右边会展示匹配的值。

这里我不过多解读,可以自己去看一下,然后输入不同的值对比一下结果。

通过上面的截图可以看到匹配会捕获两个值,第一个是环境变量的名称,第二个是环境变量的值。

然后对值进行处理,首先去掉首尾的空格,然后通过正则去掉首尾的引号,最后再将转义的换行符转换还原。

经过上面的处理,就可以将每一行的环境变量添加到obj对象中了,最后返回obj对象。

感谢各位的阅读,以上就是“dotenv怎么从.env文件中读取环境变量”的内容了,经过本文的学习后,相信大家对dotenv怎么从.env文件中读取环境变量这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯