讀完 Vue 發布源碼,小姐姐回答了 leader 的提問,并優化了項目發布流程~

大家好,我是若川。這是 源碼共讀 第三期活動,紀年小姐姐的第三次投稿。紀年小姐姐學習完優化了自己的項目發布流程,而且回答了leader對她的提問,來看看她的思考和實踐。

第三期是 Vue 3.2 發布了,那尤雨溪是怎么發布 Vue.js 的?。不知不覺,源碼共讀已經進行了快一個月,有些小伙伴表示對面試和工作很有幫助,學完立馬能用。如果你也感興趣可以加我微信 ruochuan12參加。

1. 學習目標和資源準備

這一期閱讀的是 Vue3 源碼中的 script/release.js 代碼,也就是 Vue.js 的發布流程。在上一期源碼閱讀中從 .github/contributing.md[1] 了解到 Vue.js 采用的是 monorepo 的方式進行代碼的管理。

monorepo 是管理項目代碼的一個方式,指在一個項目倉庫 (repo) 中管理多個模塊/包 (package),不同于常見的每個 package 都建一個 repo。

剛好我最近搭建組件庫也是使用 monorepo 的方式去管理包。monorepo 有個缺點,因為每個包都維護著自己的 dependencies,那么在 install 的時候會導致 node_modules 的體積非常大。目前最常見的 monorepo 解決方案是使用 lerna 和 yarn 的 workspaces 特性去處理倉庫的依賴,我搭建的組件庫也是使用了 lerna 和 yarn。但 Vue3 的包管理沒有使用 lerna,它是怎么管理依賴包的版本號呢?讓我們跟著源碼一探究竟。

Lerna[2] 是一個管理工具,用于管理包含多個軟件包(package)的 JavaScript 項目,針對使用 git 和 npm 管理多軟件包代碼倉庫的工作流程進行優化。

學習目標:

1)學習 release.js 源碼,輸出記錄文檔。

資源準備:

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 (工作區),Workspace 可以更好的統一管理有多個項目的倉庫。

  • 管理依賴關系便捷:每個項目使用獨立的 package.json 管理依賴,可以使用 yarn 命令一次性安裝或者升級所有依賴,無需在每個目錄下分別安裝依賴

  • 降低磁盤空間占用:可以使多個項目共享同一個 node_modules 目錄

3. release.js 文件解讀

先手動跑一遍 yarn run release --dry,控制臺會輸出以下信息(多余信息已省略),從控制臺日志看出來,發布 Vue.js 會經歷以下幾個步驟:

//?確認發布版本號
??Select?release?type?...
>?patch?(3.2.3)minor?(3.3.0)major?(4.0.0)custom
//?執行測試用例
Running?tests...
//?更新依賴版本
Updating?cross?dependencies...
//?打包編譯所有包
Building?all?packages...
//?生成?changelog
conventional-changelog?-p?angular?-i?CHANGELOG.md?-s
//?提交代碼
Committing?changes...
//?發布包
Publishing?packages...
//?推送代碼到?GitHub
Pushing?to?GitHub...

初步了解發布流程后,來看看 release.js 源碼做了什么,先看入口函數 main()

main 函數

代碼太多就不貼代碼了,記錄一下思路和思考

  1. 確認要發布的版本:

    • 如果從命令行獲取到了版本號,先驗證版本號規范,再次確認版本號

    • 如果命令行沒有輸入版本號,會讓用戶選擇一個版本發布

確認版本號使用了一個庫叫 semver,它的作用是用于版本校驗比較。

//?目的是獲取命令行參數(也就是允許用戶自定義輸入版本號,比如?yarn?release?v3.5.0)
const?args?=?require('minimist')(process.argv.slice(2))
let?targetVersion?=?args._[0]
  1. 執行測試用例

const?execa?=?require('execa')
const?run?=?(bin,?args,?opts?=?{})?=>?execa(bin,?args,?{?stdio:?'inherit',?...opts?})
const?bin?=?name?=>?path.resolve(__dirname,?'../node_modules/.bin/'?+?name)if?(!skipTests?&&?!isDryRun)?{//?bin("jest")?先獲取?node_modules/.bin/jest?的目錄,run?的本質就是執行命令行//?這行代碼的意思就相當于在命令終端,項目根目錄運行 ./node_modules/.bin/jest 命令。await?run(bin('jest'),?['--clearCache'])await?run('yarn',?['test',?'--bail'])
}?else?{console.log(`(skipped)`)
}
  1. 更新依賴版本

//?1)獲取?packages?目錄下的所有包
const?packages?=?fs.readdirSync(path.resolve(__dirname,?'../packages')).filter(p?=>?!p.endsWith('.ts')?&&?!p.startsWith('.'))
//?1)獲取包的根目錄路徑
const?getPkgRoot?=?pkg?=>?path.resolve(__dirname,?'../packages/'?+?pkg)
//?2)更新根目錄和?packages?目錄下每個包的?package.json?的版本號
function?updateVersions(version)?{}
//?3)實現更新?package.json?版本號的,以及更新依賴包的版本號
function?updatePackage(pkgRoot,?version)?{}
//?4)實現更新與?vue?相關依賴包的版本號
function?updateDeps(pkg,?depType,?version)?{}
  1. 打包編譯所有包

這部分涉及另外一個文件 script/build.js,這個文件主要是將各個包打包在對應的目錄下,比如打包一個依賴就運行一次yarn build,如果有多個包,就異步循環調用打包命令。核心代碼如下:

/***?迭代打包*?@param?{*}?maxConcurrency?最大并發*?@param?{*}?source?目錄*?@param?{*}?iteratorFn?構建函數(核心就是運行?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);
}
  1. 生成 CHANGELOG 文件

主要運行的是這行命令:conventional-changelog -p angular -i CHANGELOG.md -s

  1. 提交代碼

先執行 git diff 命令,檢查文件是否有修改,如果有,執行 git add 和 git commit 命令

  1. 發布包

最后執行的命令是,yarn publish,發布新版本和打 Tag

  1. 推送到 GitHub

主要運行的命令:

    • 打 tag:git tag ${version}

    • 推送 tag:git push origin refs/tags/${version}

    • 提交代碼到遠程倉庫:git push

至此,release 發布流程已經分析完了。

release 發布流程

4. 感想

回答一下開篇的問題,Vue 是如何管理版本號呢?閱讀完源碼我們會分現,在發版的時候會統一更新所有包的 package.json 的版本號。對比我在搭建組件庫過程中使用的 lerna,其實 lerna 是把 release 這一套流程封裝成了一個包,它里面處理發包的流程跟 Vue Release 流程基本是一致的。

這次的源碼解讀解答了我的一些疑惑。在我搭建組件庫的過程中,我一開始了解到的是一個組件一個目錄,單包推送到 npm 私庫。這樣做的缺點很明顯,需要在每個目錄安裝一遍依賴,單獨處理版本號。后來了解到了 yarn workspace,知道它可以處理依賴安裝的問題,但版本號的處理還是沒有解決方案。于是我去尋找業內比較流行的解決辦法,發現大部分是使用了 lerna。

于是我向我的 TL 溝通詢問,可否采用 yarn + lerna 的方式來搭建組件庫。我記得特別清楚他反問我,問我 lerna 解決了什么問題,我支支吾吾回答了官網上的介紹,因為我當時對 lerna 的了解僅停留在官網以及它的常用命令,實際上我不知道它解決了什么問題。TL 見我答不上來,回復了我一句【如無必要,勿增實體】。

通過這次的源碼閱讀,我可以回答 TL 反問我的那個問題了,lerna 解決的是發包流程中版本號處理,自動生成 CHANGELOG 文件,提交代碼,發布包,推送到倉庫這幾個問題,它把這幾個流程封裝成命令供用戶使用。它不是搭建組件庫非必要引入的工具,雖然引用了 lerna 會增加了新的復雜度,但在不了解發包流程的前期使用 lerna 可以使組件庫開發者更專注于組件開發的工作上,而不需要過度關注如何發包。

5. 實踐

經過一番思考,我認為引入 lerna 確實給系統增加了一些復雜度,因為它要求開發人員額外學習 lerna 的一些知識和命令,增加了學習成本以及系統復雜度。我覺得可以參考 Vue 的 release.js,寫一個適用于項目的構建發版腳本用來發包,降低系統復雜度。

邏輯代碼基本與 Vue3 的 release.js 和 build.js 一致,去掉了一些沒必要的代碼,比如單元測試和一些環境判斷。還修改了一下 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?私信 江西?拉你進群。


推薦閱讀

我在阿里招前端,該怎么幫你(可進面試群)
我讀源碼的經歷

初學者也能看懂的 Vue3 源碼中那些實用的基礎工具函數
老姚淺談:怎么學JavaScript?

·················?若川簡介?·················

你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列》多篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結,已經寫了7篇,點擊查看年度總結。
同時,活躍在知乎@若川,掘金@若川。致力于分享前端開發經驗,愿景:幫助5年內前端人走向前列。

識別方二維碼加我微信、拉你進源碼共讀

今日話題

略。歡迎分享、收藏、點贊、在看我的公眾號文章~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/275518.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/275518.shtml
英文地址,請注明出處:http://en.pswp.cn/news/275518.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

小程序背景圖片的坑

本人是前端菜鳥一個&#xff0c;比小白還要白&#xff0c;這完全是自己的經驗總結&#xff0c;并不是要給各位分享什么寶貴經驗哈&#xff0c;各位大佬不喜勿噴&#xff0c;不然會打擊到我的哈哈因為公司要求做幾個小程序的頁面&#xff0c;我不得不拾起丟棄了幾個月的小程序開…

SimpleAdapter類使用方法

SimpleAdapter的構造函數是&#xff1a; public SimpleAdapter (Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) 官方說明了其各個參數含義&#xff0c;我這里根據自己的理解解釋下&#xff1a; 第一個context&…

小程序 富文本自適應屏幕_自適應文本:跨屏幕尺寸構建可讀文本

小程序 富文本自適應屏幕Many of you may already know about responsive web design. Cited from Wikipedia, responsive web design (RWD) is an approach to web design that makes web pages render well on a variety of devices and windows or screen sizes. The respon…

Vue、React 之間如何實現代碼移植?

大家好&#xff0c;我是若川。面對前端最火的兩個框架&#xff0c;學 React 還是 Vue &#xff1f;這可能是每個前端人都曾糾結過的問題。不過&#xff0c;現在你不用糾結了——因為很多公司都是兩個框架都有大量的應用&#xff0c;取決于不同團隊的技術選型&#xff0c;特別是…

linux mariadb 亂碼,配置mariadb遠程訪問權限,解決數據庫亂碼問題

配置mariadb遠程訪問權限&#xff1a;1)登錄數據庫:# mysql -uroot -p2)配置授權數據庫用戶遠程訪問權限&#xff0c;%表示所有遠程IP&#xff0c;也可以指定IP。WITH GRANT OPTION表示mysql數據庫的grant表中重新加載權限數據&#xff1a;GRANT ALL PRIVILEGES ON *.* TO 用戶…

平面設計師和ui設計師_游戲設計師的平面設計

平面設計師和ui設計師Design is a very ancient practice, but graphic design really found its core principles post World War One. Games are also very ancient but video games are still finding their feet. I think graphic design has a few things to teach people…

從零開發一個命令行腳手架工具 等

大家好&#xff0c;我是若川。今天周末&#xff0c;話不多說&#xff0c;這一次花了幾小時精心為大家挑選了20余篇好文&#xff0c;供大家閱讀學習。本文閱讀技巧&#xff0c;先粗看標題&#xff0c;感興趣可以都關注一波&#xff0c;絕對不虧。前端宇宙小編就職于某大廠&#…

linux的HAL庫函數,STM32 HAL庫 IIC 協議庫函數

/* 第1個參數為I2C操作句柄第2個參數為從機設備地址第3個參數為從機寄存器地址第4個參數為從機寄存器地址長度第5個參數為發送的數據的起始地址第6個參數為傳輸數據的大小第7個參數為操作超時時間 */HAL_I2C_Mem_Write(&hi2c2,salve_add,0,0,PA_BUFF,sizeof(PA_BUFF),0x10)…

pku acm 2140 Herd Sums http://acm.pku.edu.cn/JudgeOnline/problem?id=2140

2140代碼短小精悍&#xff1a;#include<stdio.h> int main() { int cnt0,i; long s; scanf("%ld",&s); for(i1;(i1)*i/2<s;i)if((s-(i-1)*i/2)%i0)cnt; printf("%d\n",cnt); return 0; }轉載于:https://www.cnblogs.com/Chinese-Coder-C…

java合成海報的工具類

2019獨角獸企業重金招聘Python工程師標準>>> package io.renren.common.utils;import cn.hutool.core.lang.Console; import io.renren.modules.oss.cloud.OSSFactory;import javax.imageio.ImageIO; import javax.imageio.stream.ImageOutputStream; import java.a…

a說b說謊b說c說謊說d說_說謊的眼睛及其同伙

a說b說謊b說c說謊說d說The eye is a complex and temperamental organ. By the end of this article, designers will have a better understanding of how the eye works with the brain, how it deconstructs images that the brain stitches back up again, and how the two…

一名運營,自學一年前端,成功入職杭州某獨角獸企業,他的面試經驗和學習方法等分享...

大家好&#xff0c;我是若川。這是我的微信群里小伙伴年年 的投稿。他是19年畢業&#xff0c;之前做的是運營相關的工作&#xff0c;在我的交流群里非常活躍&#xff0c;自學一年前端&#xff0c;目前成功轉行入職杭州一家獨角獸企業。相信他的文章能帶給大家一些啟發和激勵。0…

linux下svn relocate,如何進行svn?relocate?操作

1。進入工作復本&#xff03;> cd ~/test2。查看倉庫地址(URL)&#xff03;> svn info路徑&#xff1a;.地址(URL)&#xff1a;http://192.168.28.1/repos/test檔案庫 UUID&#xff1a;a81f9bed-3506-0410-b369-e50476f75162修訂版&#xff1a;44節點種類&#xff1a;目錄…

教你怎么買虛擬空間(轉)

虛擬空間是什么?經常聽到站長們在群里問&#xff0c;哪里的虛擬空間好?哪里的虛擬空間性能好?哪里的虛擬空間便宜?虛擬空間是當今IDC行業的一個重要銷售產品&#xff0c;虛擬空間也是中國站長們建設網站中最常應用的網站載體。各種數據說明&#xff0c;虛擬空間的好壞能影響…

React筆記-事件分發

事件分發 之前講述了事件如何綁定在document上&#xff0c;那么具體事件觸發的時候是如何分發到具體的監聽者呢&#xff1f;我們接著上次注冊的事件代理看。當我點擊update counter按鈕時&#xff0c;觸發注冊的click事件代理。 function dispatchInteractiveEvent(topLevelTyp…

百度指數可視化_可視化指數

百度指數可視化Abstract:– Analysis of the visual representations of exponentials.– Proposals to solve current visualization issues.– Call to discussion to come up with a better visual representation convention.抽象&#xff1a; –分析指數的視覺表示形式。…

qemu+linux+x86+64,kvm 內部錯誤:無法找到適合 x86_64 的模擬器

本文將為您描述kvm 內部錯誤&#xff1a;無法找到適合 x86_64 的模擬器,教程操作方法:0x00 問題安裝完 KVM 之后&#xff0c;啟動管理工具報錯&#xff1a;內部錯誤&#xff1a;無法找到適合 x86_64 的模擬器于是查看 libvirtd 服務狀態&#xff0c;查看到以下內容&#xff1a;…

阿里云謙大佬:時間精力有限的情況下如何高效學習前端?

大家好&#xff0c;我是若川。最近組織了源碼共讀活動1個月&#xff0c;200人&#xff0c;一起讀了4周源碼&#xff0c;歡迎加我微信 ruochuan12 進群參與。今天分享一篇阿里云謙大佬的文章。昨天在群里也有小伙伴說到&#xff1a;大佬們是需要什么學什么&#xff0c;新手一般是…

JQuery小記

訪問dom元素 $代表整個dom tree $("#content") $("p") $("li .red") 字符串轉換為json對象 $.parseJSON ajax $.ajax({type: "post",url: "GetUser.ashx",success: function (data) {var t "";var json $.pars…

React個人整理

React基礎//ReactDOM.render(reactWhat,domWhere)在瀏覽器中渲染應用的一種途徑 //React.DOM表示預定義好的HTML元素集合 //React.DOM.h1(attributes,children)表示一個預定義的React 組件 //h1()第一個參數接收一個對象&#xff0c;用于指定該組件的任何屬性&#xff08;比如i…