浅读一下dotenv的主干逻辑的源码

start

  • 前面学习了 process.env
  • 有用到 这么一个插件: dotenv
  • 看一下 dotenv 的源码

之前如何使用的?

let a = require('dotenv').config()

console.log(process.env.a)

开始

  1. 下载
npm i dotenv
  1. 直奔主题

    • package.json
    • main 属性对应的文件
      在这里插入图片描述
  2. 阅读源码
    main.js

const fs = require('fs')
const path = require('path')
const os = require('os')

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

// Parser src into an Object 解析src为一个对象
function parse(src) {
  const obj = {}

  // Convert buffer to string
  let lines = src.toString()

  // Convert line breaks to same format
  lines = lines.replace(/\r\n?/gm, '\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$/gm, '$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][DEBUG] ${message}`)
}

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

// Populates process.env from .env file  从文件 .env 向 process.env 添加数据
function config(options) {
  // 1. 获取当前进程执行的路径对应的  .env文件
  let dotenvPath = path.resolve(process.cwd(), '.env')
  // 2. 定义编码格式
  let encoding = 'utf8'
  const debug = Boolean(options && options.debug)
  const override = Boolean(options && options.override)

  // 3. 接受一些参数,用来修改路径和编码格式
  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   指定编码返回一个字符串而不是一个缓冲区
    // 4. 这里读取了文件,返回的字符串,通过 parse 将字符串转换为对象
    const parsed = DotenvModule.parse(fs.readFileSync(dotenvPath, { encoding }))

    // 5. 遍历返回的对象的 key 分别添加到 process.env 中
    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]
        }

        // debug模式
        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`
            )
          }
        }
      }
    })

    // 6. 返回值是 { parsed:parsed } 这里简写了。
    return { parsed }
  } catch (e) {
    if (debug) {
      _log(`Failed to load ${dotenvPath} ${e.message}`)
    }

    return { error: e }
  }
}

const DotenvModule = {
  config,
  parse,
}

module.exports.config = DotenvModule.config
module.exports.parse = DotenvModule.parse
module.exports = DotenvModule

总结

源码也就 100 多行

  • 读取 .env 文件
  • 将读取的内容转换成对象
  • 遍历读取到的对象,将属性绑定到 process.env

没啥难度,可能就是正则写的人看不懂。。。。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lazy_tomato

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值