項目中常用的 .env 文件原理源碼解析
前言
dotenv
是一個用于加載環(huán)境變量的庫,在 Node.js 應用程序中可以使用它來簡化對環(huán)境變量的訪問。在日常開發(fā)中起到了很重要的作用。
學習目標:
- 學會 dotenv 原理和實現(xiàn)
- 學會使用 fs模塊 獲取文件并解析
資源:
源碼地址:dotenv
如何使用
使用 dotenv
庫,可以在應用程序中創(chuàng)建一個名為 .env
的文件,并在該文件中存儲環(huán)境變量。然后,可以使用 dotenv
庫將這些變量加載到 Node.js 應用程序中。
例如,您可以在 .env
文件中存儲以下內(nèi)容:
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
函數(shù)處理后的路徑。
path.resolve
函數(shù)會從右到左依次遍歷參數(shù),并返回一個絕對路徑。函數(shù)的第一個參數(shù)是 process.cwd
,它返回 Node.js 進程的當前工作目錄。第二個參數(shù)是字符串 '.env',它表示要在當前工作目錄中查找的文件名。
之后會進行一些參數(shù)的判斷,如果參數(shù)中有path這個變量,則使用_resolveHome函數(shù)處理:
function _resolveHome (envPath) { return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath }
os.homedir
函數(shù)返回當前用戶的主目錄路徑。
_resolveHome 函數(shù)可用于將以波浪號開頭的路徑解析為主目錄的實際路徑。例如,如果 envPath
等于 '~/documents/file.txt',則函數(shù)將返回 '/home/user/documents/file.txt'(在基于 Unix 的系統(tǒng)上)或 'C:\Users\user\documents\file.txt'(在 Windows 上)。
解析文件
// 使用 `fs.readFileSync` 函數(shù)以指定的編碼方式從文件系統(tǒng)中讀取文件內(nèi)容 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
中的內(nèi)容。
const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg
這個正則表達式的目的是匹配類似于環(huán)境變量的行。它可以匹配以下格式的行:
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循環(huán)將所有的鍵添加到process.env 中。
總結
dotenv 的功能用一句話來概括就是:解析env文件將其變量添加到process.env中,其中解析部分主要是使用了正則表達式來匹配4種格式的鍵值對。
以上就是項目中常用的 .env 文件原理源碼解析的詳細內(nèi)容,更多關于.env 文件原理的資料請關注腳本之家其它相關文章!
相關文章
JavaScript選擇器函數(shù)querySelector和querySelectorAll
這篇文章主要介紹了?JavaScript選擇器函數(shù)querySelector和querySelectorAll,下面文章圍繞querySelector和querySelectorAll的相關資料展開詳細內(nèi)容,需要的朋友可以參考一下2021-11-11webpack5之output和devServer的publicPath區(qū)別示例詳解
這篇文章主要為大家介紹了webpack5之output和devServer的publicPath區(qū)別示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12微信小程序 less文件編譯成wxss文件實現(xiàn)辦法
這篇文章主要介紹了微信小程序 less文件編譯成微信小程序wxss文件實現(xiàn)辦法的相關資料,這里給出具體實現(xiàn)方法,需要的朋友可以參考下2016-12-12