專案中常用的 .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種格式的鍵值對。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69901823/viewspace-2933335/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Spartacus 專案中 .env-cmdrc 檔案的作用是什麼?
- SpringMVC原始碼分析:POST請求中的檔案處理SpringMVC原始碼
- SpringBoot專案配置檔案中密碼的加密Spring Boot密碼加密
- vue原始碼分析系列之入口檔案分析Vue原始碼
- Nuxt3專案中,在構建專案時,無法獲取到 .env 檔案的變數,怎麼破?UX變數
- Springboot 載入配置檔案原始碼分析Spring Boot原始碼
- 深入理解 Laravel 中.env 檔案讀取Laravel
- jetty啟動web專案原始碼分析JettyWeb原始碼
- .Net Core中的配置檔案原始碼解析原始碼
- RyuBook1.0案例一:SwitchingHub專案原始碼分析原始碼
- 走進開源專案 - urlcat 原始碼分析原始碼
- Egg.js 原始碼分析-專案啟動JS原始碼
- springboot專案中yaml檔案Spring BootYAML
- Laravel 配置多環境env檔案Laravel
- 【Blazor】1-Blazor專案檔案分析Blazor
- 對專案中檔案做出更改,Docker會使用本地原始碼還是從遠端下載的程式碼?Docker原始碼
- 入口檔案開始,分析Vue原始碼實現Vue原始碼
- class檔案的基本結構及proxy原始碼分析二原始碼
- Android 原始碼分析(一)專案構建過程Android原始碼
- Django 專案如何通過載入不同 env 檔案來區分不同環境Django
- 學習過程中,專案檔案、程式碼疑惑點
- 原始碼解析Flask的配置檔案原始碼Flask
- 鴻蒙輕核心原始碼分析:檔案系統LittleFS鴻蒙原始碼
- 34套Java專案教程+原始碼包含Java swing專案 Java web專案 Java控制檯專案(視訊教程+原始碼)Java原始碼Web
- Vue原始碼探究-原始碼檔案組織Vue原始碼
- 使用 functrace 輔助進行 Go 專案原始碼分析Go原始碼
- 取證中exe檔案的分析
- Golang專案中讀取配置檔案Golang
- Fabric 1.0原始碼分析(2) blockfile(區塊檔案儲存)原始碼BloC
- Fabric 1.0原始碼分析(22)Ledger #blkstorage(block檔案儲存)原始碼BloC
- Linux系統中建立檔案常用的方法!Linux
- Swift原始碼專案編譯Swift原始碼編譯
- 重新命名vue檔案後ts爆紅。檔案xxx不在專案xxx的檔案列表中。專案必須列出所有檔案,或使用 "include" 模式。Vue模式
- Laravel 和 Lumen 中通過環境變數配置對應的 env 檔案Laravel變數
- SpringBoot原始碼解析-配置檔案的載入Spring Boot原始碼
- Fabric 1.0原始碼分析(28) Orderer #localconfig(Orderer配置檔案定義)原始碼
- PHP檔案分享系統原始碼PHP原始碼
- Linux中監視日誌檔案常用的命令!Linux