.env文件是如何設(shè)置環(huán)境變量的

廢話不多說,上菜?。?!

搞一手dotenv的代碼:

git clone https://github.com/motdotla/dotenv.git
# npm i -g yarn
cd dotenv && yarn i

dotenv的作用就是將.env文件中的變量放入process.env中

接下來看一下我們常用.env文件,大概猜測下dotenv到底干了什么

// .env
NODE_ENV=development
URL='http://xxx.cn'
  1. 首先要獲取文件內(nèi)容
  2. 解析文件內(nèi)容(類似于key=value)
  3. 將解析內(nèi)容遍歷放進(jìn)process.env內(nèi)

來看源碼:


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

function log (message /*: string */) {
  console.log(`[dotenv][DEBUG] ${message}`)
}

const NEWLINE = '\n'
const RE_INI_KEY_VAL = /^\s*([\w.-]+)\s*=\s*(.*)?\s*$/
const RE_NEWLINES = /\\n/g
const NEWLINES_MATCH = /\r\n|\n|\r/

// Parses src into an Object
function parse (src /*: string | Buffer */, options /*: ?DotenvParseOptions */) /*: DotenvParseOutput */ {
  const debug = Boolean(options && options.debug)
  const obj = {}

  // convert Buffers before splitting into lines and processing
  src.toString().split(NEWLINES_MATCH).forEach(function (line, idx) {
    // matching "KEY' and 'VAL' in 'KEY=VAL'
    const keyValueArr = line.match(RE_INI_KEY_VAL)
    // matched?
    if (keyValueArr != null) {
      const key = keyValueArr[1]
      // default undefined or missing values to empty string
      let val = (keyValueArr[2] || '')
      const end = val.length - 1
      const isDoubleQuoted = val[0] === '"' && val[end] === '"'
      const isSingleQuoted = val[0] === "'" && val[end] === "'"

      // if single or double quoted, remove quotes
      if (isSingleQuoted || isDoubleQuoted) {
        val = val.substring(1, end)

        // if double quoted, expand newlines
        if (isDoubleQuoted) {
          val = val.replace(RE_NEWLINES, NEWLINE)
        }
      } else {
        // remove surrounding whitespace
        val = val.trim()
      }

      obj[key] = val
    } else if (debug) {
      log(`did not match key and value when parsing line ${idx + 1}: ${line}`)
    }
  })

  return obj
}

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

// Populates process.env from .env file
function config (options /*: ?DotenvConfigOptions */) /*: DotenvConfigOutput */ {
  let dotenvPath = path.resolve(process.cwd(), '.env')
  let encoding /*: string */ = 'utf8'
  let debug = false

  if (options) {
    if (options.path != null) {
      dotenvPath = resolveHome(options.path)
    }
    if (options.encoding != null) {
      encoding = options.encoding
    }
    if (options.debug != null) {
      debug = true
    }
  }

  try {
    // specifying an encoding returns a string instead of a buffer
    const parsed = parse(fs.readFileSync(dotenvPath, { encoding }), { debug })

    Object.keys(parsed).forEach(function (key) {
      if (!Object.prototype.hasOwnProperty.call(process.env, key)) {
        process.env[key] = parsed[key]
      } else if (debug) {
        log(`"${key}" is already defined in \`process.env\` and will not be overwritten`)
      }
    })

    return { parsed }
  } catch (e) {
    return { error: e }
  }
}

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

代碼挺長,主要看parsed方法大概意思就是在處理獲取的文件內(nèi)容,將轉(zhuǎn)化為一個對象
config方法就是獲取文件內(nèi)容,將parsed方法妝花的對象進(jìn)行遍歷遍歷賦值給process.env,返回對象

都這兒了,那瀏覽器怎么訪問到環(huán)境變量呢,process.env只在的node環(huán)境中,此時就需要做一些操作,在構(gòu)建時將環(huán)境變量在別地方再存一份

webpack 的 DefinePlugin,dotenv-webpack二者做了差不多的事,具體實現(xiàn)思路就是構(gòu)建時將process.env的內(nèi)容copy一份,便于區(qū)分直接以'process.env.xxx'為key,將對應(yīng)值進(jìn)行賦值

有興趣的可以看下dotenv-webpack源碼,它是結(jié)合了dotenv和webpack的DefinePlugin開發(fā)的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容