阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

项目中常用的 .env 文件原理源码分析

46次阅读
没有评论

共计 3033 个字符,预计需要花费 8 分钟才能阅读完成。

导读 这篇文章主要为大家介绍了项目中常用的 .env 文件原理源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

dotenv 是一个用于加载环境变量的库,在 Node.js 应用程序中可以使用它来简化对环境变量的访问。在日常开发中起到了很重要的作用。

如何使用

使用 dotenv 库,可以在应用程序中创建一个名为 .env 的文件,并在该文件中存储环境变量。然后,可以使用 dotenv 库将这些变量加载到 Node.js 应用程序中。

例如,您可以在 .env 文件中存储以下内容:

DB_HOST=localhost
DB_USERNAME=user
DB_PASSWORD=password

使用以下代码将这些变量加载到应用程序中:

require('dotenv').config();
const dbHost = process.env.DB_HOST;
const dbUsername = process.env.DB_USERNAME;
const dbPassword = process.env.DB_PASSWORD;
源码解析

阅读源码之前,可以猜测 dotenv 所做的工作有如下几点。

  • 读取 .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}
      }
    }

    代码中定义了一个变量 dotenvPath,并将其赋值为使用 path.resolve 函数处理后的路径。

    path.resolve 函数会从右到左依次遍历参数,并返回一个绝对路径。函数的第一个参数是 process.cwd,它返回 Node.js 进程的当前工作目录。第二个参数是字符串 ‘.env’,它表示要在当前工作目录中查找的文件名。

    之后会进行一些参数的判断,如果参数中有 path 这个变量,则使用_resolveHome 函数处理:

    function _resolveHome (envPath) {return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath
    }

    os.homedir 函数返回当前用户的主目录路径。

    _resolveHome 函数可用于将以波浪号开头的路径解析为主目录的实际路径。例如,如果 envPath 等于 ‘~/documents/file.txt’,则函数将返回 ‘/home/user/documents/file.txt’(在基于 Unix 的系统上)或 ‘C:\Users\user\documents\file.txt’(在 Windows 上)。

    解析文件
    // 使用 `fs.readFileSync` 函数以指定的编码方式从文件系统中读取文件内容
    const parsed = DotenvModule.parse(fs.readFileSync(dotenvPath, { encoding}))
    // 解析文件
    function parse (src) {const obj = {}
      // 转为 string 类型
      let lines = src.toString()
      // 将换行符转换为相同的格式
      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 来匹配字符串 lines 中的内容。

    const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg

    这个正则表达式的目的是匹配类似于环境变量的行。它可以匹配以下格式的行:

    VARNAME=value
    VARNAME: value
    export VARNAME=value
    export VARNAME: value

    最后会返回一个包含所有变量的对象。

    赋值操作
    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}
    }

    拿到解析后的对象,使用 Object.keys(parsed) 获取所有的键,然后使用 forEach 循环将所有的键添加到 process.env 中。

    dotenv 的功能用一句话来概括就是:解析 env 文件将其变量添加到 process.env 中,其中解析部分主要是使用了正则表达式来匹配 4 种格式的键值对。

    阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

    腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

    代金券:在阿里云专用满减优惠券

    正文完
    星哥说事-微信公众号
    post-qrcode
     0
    星锅
    版权声明:本站原创文章,由 星锅 于2024-07-24发表,共计3033字。
    转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
    【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
    阿里云-最新活动爆款每日限量供应
    评论(没有评论)
    验证码
    【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中