您好,登錄后才能下訂單哦!
這篇文章主要講解了“dotenv怎么從.env文件中讀取環境變量”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“dotenv怎么從.env文件中讀取環境變量”吧!
dotenv
從.env
文件中讀取環境變量,然后將其添加到process.env
中。這是一個非常簡單的庫,但是它在開發中非常有用,因為它允許你在.env
文件中存儲敏感信息,而不是將其存儲在代碼中。
現在很多庫都支持.env
文件,例如create-react-app
,vue-cli
,next.js
等。
根據README
,dotenv
只有兩個方法:
config
:讀取.env
文件并將其添加到process.env
中。
parse
:解析一段包含環境變量的字符串或Buffer
,并返回一個對象。
const dotenv = require('dotenv') // 讀取.env文件并將其添加到process.env中 dotenv.config() // 解析一段包含環境變量的字符串或Buffer,返回一個對象 const config1 = dotenv.parse('FOO=bar\nBAR=foo') console.log(config1) // { FOO: 'bar', BAR: 'foo' } const buffer = Buffer.from('FOO=bar\nBAR=foo') const config2 = dotenv.parse(buffer) console.log(config2) // { FOO: 'bar', BAR: 'foo' }
可以看到,dotenv
的使用非常簡單,通常我們只需要調用config
方法即可。
還有一種方法是預加載,直接通過node -r dotenv/config
來運行腳本,這樣就不需要在腳本中引入dotenv
了。
源碼在lib/main.js
中,先來看一下全部的代碼:
const fs = require('fs') const path = require('path') const os = require('os') const packageJson = require('../package.json') const version = packageJson.version const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\'|[^'])*'|\s*"(?:\"|[^"])*"|\s*`(?:\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg // Parser src into an Object function parse (src) { const obj = {} // Convert buffer to string let lines = src.toString() // Convert line breaks to same format 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 } function _log (message) { console.log(`[dotenv@${version}][DEBUG] ${message}`) } function _resolveHome (envPath) { return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath } // Populates process.env from .env file 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 } } 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 } } 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
可以看到最后導出的是一個對象,包含了config
和parse
兩個方法。
config
方法的作用是讀取.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) }
首先定義了一些變量:
dotenvPath
是.env
文件的路徑
encoding
是文件的編碼
debug
和override
分別表示是否開啟調試模式和是否覆蓋已有的環境變量。
if (options) { if (options.path != null) { dotenvPath = _resolveHome(options.path) } if (options.encoding != null) { encoding = options.encoding } }
然后判斷了一下options
是否存在,如果存在的話,就會根據options
的值來修改dotenvPath
和encoding
的值。
const parsed = DotenvModule.parse(fs.readFileSync(dotenvPath, { encoding }))
然后是調用parse
方法來解析.env
文件,parse
方法的實現在下面會講到。
這里是只用fs.readFileSync
來讀取.env
文件,然后將其傳入parse
方法中,接著往下:
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`) } } } })
這里是遍歷parsed
對象,然后將其添加到process.env
中,如果process.env
中已經存在了該環境變量,那么就會根據override
的值來決定是否覆蓋。
debug
的值表示是否開啟調試模式,如果開啟了調試模式,那么就會打印一些日志。
最后就是直接返回parsed
對象。
parse
方法的作用是解析.env
文件,將其轉換為一個對象。
const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\'|[^'])*'|\s*"(?:\"|[^"])*"|\s*`(?:\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg function parse (src) { const obj = {} // Convert buffer to string let lines = src.toString() // Convert line breaks to same format 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
,用來匹配.env
文件中的每一行。
然后是將src
轉換為字符串,然后將換行符統一為\n
。
接著就是核心,通過正則表達式的特性通過while
循環來匹配每一行。
這個正則著實有點復雜,我是正則渣渣,可以在regex101查看一下。
這個正則上面標出了三種顏色,和下面的匹配的值的顏色相互對應,然后右邊會展示匹配的值。
這里我不過多解讀,可以自己去看一下,然后輸入不同的值對比一下結果。
通過上面的截圖可以看到匹配會捕獲兩個值,第一個是環境變量的名稱,第二個是環境變量的值。
然后對值進行處理,首先去掉首尾的空格,然后通過正則去掉首尾的引號,最后再將轉義的換行符轉換還原。
經過上面的處理,就可以將每一行的環境變量添加到obj
對象中了,最后返回obj
對象。
感謝各位的閱讀,以上就是“dotenv怎么從.env文件中讀取環境變量”的內容了,經過本文的學習后,相信大家對dotenv怎么從.env文件中讀取環境變量這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。