读完 Vue 发布源码,小姐姐回答了 leader 的提问,并优化了项目发布流程~
大家好,我是若川。這是 源碼共讀 第三期活動,紀(jì)年小姐姐的第三次投稿。紀(jì)年小姐姐學(xué)習(xí)完優(yōu)化了自己的項目發(fā)布流程,而且回答了leader對她的提問,來看看她的思考和實踐。
第三期是 Vue 3.2 發(fā)布了,那尤雨溪是怎么發(fā)布 Vue.js 的?。不知不覺,源碼共讀已經(jīng)進(jìn)行了快一個月,有些小伙伴表示對面試和工作很有幫助,學(xué)完立馬能用。如果你也感興趣可以加我微信 ruochuan12參加。
1. 學(xué)習(xí)目標(biāo)和資源準(zhǔn)備
這一期閱讀的是 Vue3 源碼中的 script/release.js 代碼,也就是 Vue.js 的發(fā)布流程。在上一期源碼閱讀中從 .github/contributing.md[1] 了解到 Vue.js 采用的是 monorepo 的方式進(jìn)行代碼的管理。
monorepo 是管理項目代碼的一個方式,指在一個項目倉庫 (repo) 中管理多個模塊/包 (package),不同于常見的每個 package 都建一個 repo。
剛好我最近搭建組件庫也是使用 monorepo 的方式去管理包。monorepo 有個缺點,因為每個包都維護(hù)著自己的 dependencies,那么在 install 的時候會導(dǎo)致 node_modules 的體積非常大。目前最常見的 monorepo 解決方案是使用 lerna 和 yarn 的 workspaces 特性去處理倉庫的依賴,我搭建的組件庫也是使用了 lerna 和 yarn。但 Vue3 的包管理沒有使用 lerna,它是怎么管理依賴包的版本號呢?讓我們跟著源碼一探究竟。
Lerna[2] 是一個管理工具,用于管理包含多個軟件包(package)的 JavaScript 項目,針對使用 git 和 npm 管理多軟件包代碼倉庫的工作流程進(jìn)行優(yōu)化。
學(xué)習(xí)目標(biāo):
1)學(xué)習(xí) release.js 源碼,輸出記錄文檔。
資源準(zhǔn)備:
Vue3 源碼地址:https://github.com/vuejs/vue-next
2. Yarn Workspace
//?vue-next/package.json?(多余的代碼已省略) {"private":?true,"version":?"3.2.2","workspaces":?["packages/*"],"scripts":?{"release":?"node?scripts/release.js"} }Yarn 從 1.0 版開始支持 Workspace (工作區(qū)),Workspace 可以更好的統(tǒng)一管理有多個項目的倉庫。
管理依賴關(guān)系便捷:每個項目使用獨立的 package.json 管理依賴,可以使用 yarn 命令一次性安裝或者升級所有依賴,無需在每個目錄下分別安裝依賴
降低磁盤空間占用:可以使多個項目共享同一個 node_modules 目錄
3. release.js 文件解讀
先手動跑一遍 yarn run release --dry,控制臺會輸出以下信息(多余信息已省略),從控制臺日志看出來,發(fā)布 Vue.js 會經(jīng)歷以下幾個步驟:
//?確認(rèn)發(fā)布版本號 ??Select?release?type?... >?patch?(3.2.3)minor?(3.3.0)major?(4.0.0)custom //?執(zhí)行測試用例 Running?tests... //?更新依賴版本 Updating?cross?dependencies... //?打包編譯所有包 Building?all?packages... //?生成?changelog conventional-changelog?-p?angular?-i?CHANGELOG.md?-s //?提交代碼 Committing?changes... //?發(fā)布包 Publishing?packages... //?推送代碼到?GitHub Pushing?to?GitHub...初步了解發(fā)布流程后,來看看 release.js 源碼做了什么,先看入口函數(shù) main()
main 函數(shù)
代碼太多就不貼代碼了,記錄一下思路和思考
確認(rèn)要發(fā)布的版本:
如果從命令行獲取到了版本號,先驗證版本號規(guī)范,再次確認(rèn)版本號
如果命令行沒有輸入版本號,會讓用戶選擇一個版本發(fā)布
確認(rèn)版本號使用了一個庫叫 semver,它的作用是用于版本校驗比較。
//?目的是獲取命令行參數(shù)(也就是允許用戶自定義輸入版本號,比如?yarn?release?v3.5.0) const?args?=?require('minimist')(process.argv.slice(2)) let?targetVersion?=?args._[0]執(zhí)行測試用例
更新依賴版本
打包編譯所有包
這部分涉及另外一個文件 script/build.js,這個文件主要是將各個包打包在對應(yīng)的目錄下,比如打包一個依賴就運行一次yarn build,如果有多個包,就異步循環(huán)調(diào)用打包命令。核心代碼如下:
/***?迭代打包*?@param?{*}?maxConcurrency?最大并發(fā)*?@param?{*}?source?目錄*?@param?{*}?iteratorFn?構(gòu)建函數(shù)(核心就是運行?build?命令)*?@returns*/ async?function?runParallel(maxConcurrency,?source,?iteratorFn)?{const?ret?=?[];const?executing?=?[];for?(const?item?of?source)?{const?p?=?Promise.resolve().then(()?=>?iteratorFn(item,?source));ret.push(p);if?(maxConcurrency?<=?source.length)?{const?e?=?p.then(()?=>?executing.splice(executing.indexOf(e),?1));executing.push(e);if?(executing.length?>=?maxConcurrency)?{await?Promise.race(executing);}}}return?Promise.all(ret); }生成 CHANGELOG 文件
主要運行的是這行命令:conventional-changelog -p angular -i CHANGELOG.md -s
提交代碼
先執(zhí)行 git diff 命令,檢查文件是否有修改,如果有,執(zhí)行 git add 和 git commit 命令
發(fā)布包
最后執(zhí)行的命令是,yarn publish,發(fā)布新版本和打 Tag
推送到 GitHub
主要運行的命令:
打 tag:git tag ${version}
推送 tag:git push origin refs/tags/${version}
提交代碼到遠(yuǎn)程倉庫:git push
至此,release 發(fā)布流程已經(jīng)分析完了。
release 發(fā)布流程4. 感想
回答一下開篇的問題,Vue 是如何管理版本號呢?閱讀完源碼我們會分現(xiàn),在發(fā)版的時候會統(tǒng)一更新所有包的 package.json 的版本號。對比我在搭建組件庫過程中使用的 lerna,其實 lerna 是把 release 這一套流程封裝成了一個包,它里面處理發(fā)包的流程跟 Vue Release 流程基本是一致的。
這次的源碼解讀解答了我的一些疑惑。在我搭建組件庫的過程中,我一開始了解到的是一個組件一個目錄,單包推送到 npm 私庫。這樣做的缺點很明顯,需要在每個目錄安裝一遍依賴,單獨處理版本號。后來了解到了 yarn workspace,知道它可以處理依賴安裝的問題,但版本號的處理還是沒有解決方案。于是我去尋找業(yè)內(nèi)比較流行的解決辦法,發(fā)現(xiàn)大部分是使用了 lerna。
于是我向我的 TL 溝通詢問,可否采用 yarn + lerna 的方式來搭建組件庫。我記得特別清楚他反問我,問我 lerna 解決了什么問題,我支支吾吾回答了官網(wǎng)上的介紹,因為我當(dāng)時對 lerna 的了解僅停留在官網(wǎng)以及它的常用命令,實際上我不知道它解決了什么問題。TL 見我答不上來,回復(fù)了我一句【如無必要,勿增實體】。
通過這次的源碼閱讀,我可以回答 TL 反問我的那個問題了,lerna 解決的是發(fā)包流程中版本號處理,自動生成 CHANGELOG 文件,提交代碼,發(fā)布包,推送到倉庫這幾個問題,它把這幾個流程封裝成命令供用戶使用。它不是搭建組件庫非必要引入的工具,雖然引用了 lerna 會增加了新的復(fù)雜度,但在不了解發(fā)包流程的前期使用 lerna 可以使組件庫開發(fā)者更專注于組件開發(fā)的工作上,而不需要過度關(guān)注如何發(fā)包。
5. 實踐
經(jīng)過一番思考,我認(rèn)為引入 lerna 確實給系統(tǒng)增加了一些復(fù)雜度,因為它要求開發(fā)人員額外學(xué)習(xí) lerna 的一些知識和命令,增加了學(xué)習(xí)成本以及系統(tǒng)復(fù)雜度。我覺得可以參考 Vue 的 release.js,寫一個適用于項目的構(gòu)建發(fā)版腳本用來發(fā)包,降低系統(tǒng)復(fù)雜度。
邏輯代碼基本與 Vue3 的 release.js 和 build.js 一致,去掉了一些沒必要的代碼,比如單元測試和一些環(huán)境判斷。還修改了一下 rollup.config.js 的配置,感覺用起來確實比 lerna 好用一些。最終效果如下:
img參考資料
[1]
.github/contributing.md: https://github.com/vuejs/vue-next/blob/master/.github/contributing.md
[2]Lerna: https://www.lernajs.cn/
最近組建了一個江西人的前端交流群,如果你是江西人可以加我微信?ruochuan12?私信 江西?拉你進(jìn)群。
推薦閱讀
我在阿里招前端,該怎么幫你(可進(jìn)面試群)
我讀源碼的經(jīng)歷
初學(xué)者也能看懂的 Vue3 源碼中那些實用的基礎(chǔ)工具函數(shù)
老姚淺談:怎么學(xué)JavaScript?
·················?若川簡介?·················
你好,我是若川,畢業(yè)于江西高校。現(xiàn)在是一名前端開發(fā)“工程師”。寫有《學(xué)習(xí)源碼整體架構(gòu)系列》多篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結(jié),已經(jīng)寫了7篇,點擊查看年度總結(jié)。
同時,活躍在知乎@若川,掘金@若川。致力于分享前端開發(fā)經(jīng)驗,愿景:幫助5年內(nèi)前端人走向前列。
識別上方二維碼加我微信、拉你進(jìn)源碼共讀群
今日話題
略。歡迎分享、收藏、點贊、在看我的公眾號文章~
總結(jié)
以上是生活随笔為你收集整理的读完 Vue 发布源码,小姐姐回答了 leader 的提问,并优化了项目发布流程~的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端学习(3166):react-hel
- 下一篇: 前端学习(3093):vue+eleme