面试官:项目中常用的 .env 文件原理是什么?如何实现?
1. 前言
大家好,我是若川。持續(xù)組織了5個月源碼共讀活動,感興趣的可以點此加我微信 ruochuan12?參與,每周大家一起學(xué)習(xí)200行左右的源碼,共同進(jìn)步。同時極力推薦訂閱我寫的《學(xué)習(xí)源碼整體架構(gòu)系列》?包含20余篇源碼文章。
本文倉庫 https://github.com/lxchuan12/dotenv-analysis.git,求個star^_^[1]
源碼共讀活動
每周一期,已進(jìn)行到19期。于是搜尋各種值得我們學(xué)習(xí),且代碼行數(shù)不多的源碼。dotenv 主文件僅118行[2],非常值得我們學(xué)習(xí)。
閱讀本文,你將學(xué)到:
1.?學(xué)會?dotenv?原理和實現(xiàn) 2.?學(xué)會使用?fs模塊?獲取文件并解析 3.?等等2. 環(huán)境準(zhǔn)備
#?推薦克隆我的項目,保證與文章同步 git?clone?https://github.com/lxchuan12/dotenv-analysis.git #?npm?i?-g?yarn cd?dotenv-analysis/dotenv?&&?yarn?i #?VSCode?直接打開當(dāng)前項目 #?code?. #?我寫的例子都在?examples?這個文件夾中,可以啟動服務(wù)本地查看調(diào)試 #?在?dotenv-analysis?目錄下 node?examples/index.js#?或者克隆官方項目 git?clone?https://github.com/motdotla/dotenv.git #?npm?i?-g?yarn cd?dotenv?&&?yarn?i #?VSCode?直接打開當(dāng)前項目 #?code?.如果需要對源碼進(jìn)行調(diào)試,可以看我的這篇文章:新手向:前端程序員必學(xué)基本技能——調(diào)試JS代碼,這里就不再贅述了。
3. dotenv 的作用
dotenv[3]
Dotenv 是一個零依賴模塊,可將 .env 文件中的環(huán)境變量加載到 process.env 中。
如果需要使用變量,則配合如下擴(kuò)展包使用。
dotenv-expand[4]
眾所周知,.env 文件在我們項目中非常常見,在 vue-cli 和 create-react-app 中都有使用。
vue-cli .env[5]
create-react-app .env[6]
4. .env 文件使用
我們項目中經(jīng)常會用到.env 文件寫法:
NAME=若川 AGE=18 BLOG=https://lxchuan12.gitee.io MP_WEIXIN='若川視野' ACTIVITY=每周一起學(xué)200行左右的源碼共讀活動 WEIXIN=加我微信?ruochuan12?參與單從這個文件來看,我們可以知道有如下功能需要實現(xiàn):
讀取 .env 文件
解析 .env 文件拆成鍵值對的對象形式
賦值到 process.env 上
最后返回解析后得到的對象
5. 簡單實現(xiàn)
根據(jù)分析問題,我們最終可以簡單把代碼實現(xiàn)如下:
const?fs?=?require('fs'); const?path?=?require('path');const?parse?=?function?parse(src){const?obj?=?{};//?用換行符?分割//?比如/***?NAME=若川*?AGE=18*?MP_WEIXIN=若川視野*?BLOG=https://lxchuan12.gitee.io*?ACTIVITY=每周一起學(xué)200行左右的源碼共讀活動*?WEIXIN=加我微信?ruochuan12?參與*/src.toString().split('\n').forEach(function(line,?index){//?用等號分割const?keyValueArr?=?line.split('=');//?NAMEkey?=?keyValueArr[0];//?若川val?=?keyValueArr[1]?||?'';obj[key]?=?val;});//?{?NAME:?'若川',?...?}return?obj; }const?config?=?function(){//?讀取?node?執(zhí)行的當(dāng)前路徑下的?.env?文件let?dotenvPath?=?path.resolve(process.cwd(),?'.env');//?按?utf-8?解析文件,得到對象//?{?NAME:?'若川',?...?}const?parsed?=?parse(fs.readFileSync(dotenvPath,?'utf-8'));//?鍵值對形式賦值到?process.env?變量上,原先存在的不賦值Object.keys(parsed).forEach(function(key){if(!Object.prototype.hasOwnProperty.call(process.env,?key)){process.env[key]?=?parsed[key];}});//?返回對象return?parsed; };console.log(config()); console.log(process.env);//?導(dǎo)出?config?parse?函數(shù) module.exports.config?=?config; module.exports.parse?=?parse;6. 繼續(xù)完善 config 函數(shù)
簡版的 config 函數(shù)還缺失挺多功能,比如:
可由用戶自定義路徑 可由用戶自定義解析編碼規(guī)則 添加?debug?模式 完善報錯輸出,用戶寫的 env 文件自由度比較大,所以需要容錯機(jī)制。根據(jù)功能,我們很容易實現(xiàn)以下代碼:
function?resolveHome?(envPath)?{return?envPath[0]?===?'~'???path.join(os.homedir(),?envPath.slice(1))?:?envPath }const?config?=?function(options){//?讀取?node?執(zhí)行的當(dāng)前路徑下的?.env?文件let?dotenvPath?=?path.resolve(process.cwd(),?'.env');//?utf8let?encoding?=?'utf8';//?debug?模式,輸出提示等信息let?debug?=?false;//?對象if?(options)?{if?(options.path?!=?null)?{//?解析路徑dotenvPath?=?resolveHome(options.path)}//?使用配置的編碼方式if?(options.encoding?!=?null)?{encoding?=?options.encoding}//?有配置就設(shè)置為?trueif?(options.debug?!=?null)?{debug?=?true}}try?{//?按?utf-8?解析文件,得到對象//?{?NAME:?'若川',?...?}//?debug?傳遞給?parse?函數(shù)?便于const?parsed?=?parse(fs.readFileSync(dotenvPath,?{?encoding?}),?{?debug?});//?鍵值對形式賦值到?process.env?變量上,原先存在的不賦值Object.keys(parsed).forEach(function(key){if(!Object.prototype.hasOwnProperty.call(process.env,?key)){process.env[key]?=?parsed[key];}?else?if?(debug)?{console.log(`"${key}"?is?already?defined?in?\`process.env\`?and?will?not?be?overwritten`);}});//?返回對象return?parsed;}catch?(e)?{return?{?error:?e?};} };dotenv 源碼中,parse 函數(shù)主要是一些正則和單雙引號、跨平臺等細(xì)致處理。這里就暫時不闡述,讀者朋友可以查看dotenv 源碼[7]。
7. 總結(jié)
鑒于文章不宜過長,文章只比較深入的分析了 config 函數(shù)。parse 函數(shù)目前沒有深入分析。
一句話總結(jié) dotenv 庫的原理。用 fs.readFileSync 讀取 .env 文件,并解析文件為鍵值對形式的對象,將最終結(jié)果對象遍歷賦值到 process.env 上。
我們也可以不看 dotenv 源碼,根據(jù) api 倒推,自己來實現(xiàn)這樣的功能。最終看看和 ?dotenv 源碼本身有什么差別。這樣也許更能鍛煉自己。或者用 ts 重構(gòu)它。
本文同時也給我們啟發(fā):圍繞工作常用的技術(shù)包和庫值得深入學(xué)習(xí),做到知其然,知其所以然。
值得一提的是:dotenv 源碼使用的是 flow 類型。vue2 源碼也是用的 flow。vue3 源碼改用 ts了。
最后可以持續(xù)關(guān)注我@若川。歡迎加我微信 ruochuan12 交流,參與 源碼共讀 活動,每周大家一起學(xué)習(xí)200行左右的源碼,共同進(jìn)步。
參考資料
[1]
本文倉庫 https://github.com/lxchuan12/dotenv-analysis.git,求個star^_^: https://github.com/lxchuan12/dotenv-analysis.git
[2]dotenv 主文件僅118行: https://github.com/motdotla/dotenv/blob/master/lib/main.js
[3]dotenv: https://github.com/motdotla/dotenv
[4]dotenv-expand: https://github.com/motdotla/dotenv-expand
[5]vue-cli .env: https://cli.vuejs.org/zh/guide/mode-and-env.html#%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F
[6]create-react-app .env: https://create-react-app.dev/docs/adding-custom-environment-variables/#what-other-env-files-can-be-used
[7]dotenv 源碼: https://github.com/motdotla/dotenv/blob/master/lib/main.js
·················?若川簡介?·················
你好,我是若川,畢業(yè)于江西高校。現(xiàn)在是一名前端開發(fā)“工程師”。寫有《學(xué)習(xí)源碼整體架構(gòu)系列》20余篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結(jié),已經(jīng)寫了7篇,點擊查看年度總結(jié)。
同時,最近組織了源碼共讀活動,幫助3000+前端人學(xué)會看源碼。公眾號愿景:幫助5年內(nèi)前端人走向前列。
識別上方二維碼加我微信、拉你進(jìn)源碼共讀群
今日話題
略。分享、收藏、點贊、在看我的文章就是對我最大的支持~
總結(jié)
以上是生活随笔為你收集整理的面试官:项目中常用的 .env 文件原理是什么?如何实现?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: awvs12 Server Except
- 下一篇: 前端学习(3038):vue+eleme