新聞中心
背景
在開(kāi)發(fā)大型項(xiàng)目時(shí), 我們通常會(huì)遇到同一工程依賴(lài)不同組件包, 同時(shí)不同的組件包之間還會(huì)相互依賴(lài)的問(wèn)題, 那么如何管理組織這些依賴(lài)包就是一個(gè)迫在眉睫的問(wèn)題.

成都創(chuàng)新互聯(lián)公司長(zhǎng)期為上1000+客戶(hù)提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為饒平企業(yè)提供專(zhuān)業(yè)的做網(wǎng)站、網(wǎng)站制作,饒平網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。
我們目前已有的方案有: Multirepo(多個(gè)依賴(lài)包獨(dú)立進(jìn)行g(shù)it管理) 和 Monorepo(所有依賴(lài)庫(kù)完全放入一個(gè)項(xiàng)目工程).
Multirepo的缺點(diǎn)在于每個(gè)庫(kù)變更之后,需要發(fā)布到線(xiàn)上,然后在項(xiàng)目中重新安裝, 打包, 發(fā)布, 最后才能更新,這樣如果依賴(lài)關(guān)系越復(fù)雜就越難以維護(hù)。Monorepo最大的缺點(diǎn)就是不便于代碼的復(fù)用和共享。
為了解決上述的問(wèn)題, lerna 這款工具誕生了, 它可以方便的管理具有多個(gè)包的 JavaScript 項(xiàng)目。同時(shí)對(duì)于組件包的開(kāi)發(fā)者和維護(hù)者, 為了讓團(tuán)隊(duì)其他成員更好的理解和使用我們開(kāi)發(fā)的組件, 搭建組件文檔和 demo 就顯得格外重要.
我們對(duì)以上提到的幾點(diǎn)問(wèn)題做一個(gè)總結(jié):
- 大型項(xiàng)目中如何管理組織依賴(lài)包及其版本問(wèn)題
- 如何高效低成本的搭建簡(jiǎn)單易用的組件文檔
- 如何配置eslint代碼規(guī)范和代碼提交規(guī)范
接下來(lái)我將針對(duì)以上問(wèn)題一一來(lái)給出解答. 如果大家想看實(shí)際的案例, 可以參考:
- best-cps | 基于lerna + dumi搭建的多包管理實(shí)踐
大型項(xiàng)目中如何管理組織依賴(lài)包及其版本問(wèn)題
這個(gè)問(wèn)題主要用我上面的提到的 lerna 工具來(lái)解決. 目前我們比較熟悉的 babel, create-react-app, vue-cli 等都使用了 lerna.
在沒(méi)使用 lerna 時(shí), 我們不同庫(kù)的組織形式可能如下:
使用 lerna 之后的庫(kù)組織結(jié)構(gòu):
以上兩個(gè)是我做的簡(jiǎn)圖, 基本可以對(duì)比出使用 lerna 前后的差異, lerna 的作用是把多個(gè)項(xiàng)目或模塊拆分為多個(gè) packages 放入一個(gè)git倉(cāng)庫(kù)進(jìn)行管理。我們可以使用它提供的命令輕松的對(duì)不同項(xiàng)目進(jìn)行管理 , 如下:
- lerna boostrap 自動(dòng)解決packages之間的依賴(lài)關(guān)系,對(duì)于packages內(nèi)部的依賴(lài)會(huì)直接采用symlink的方式關(guān)聯(lián)
- lerna publish 依賴(lài)git檢測(cè)文件改動(dòng),自動(dòng)發(fā)布,管理版本號(hào)
- lerna create 創(chuàng)建一個(gè) lerna 管理的package包
- lerna clean 刪除所有包下面的node_modules目錄,也可以刪除指定包下面的node_modules
同時(shí) lerna 還會(huì)根據(jù) git 提交記錄,自動(dòng)生成 changelog. 當(dāng)然 lerna 還提供了很多有用的命令, 大家感興趣可以在官網(wǎng)學(xué)習(xí).
接下來(lái)我就帶大家從零搭建一個(gè)使用 lerna 管理的多包項(xiàng)目.
上圖是我們包的依賴(lài)關(guān)系, 首先我們需要全局安裝一下 lerna.
項(xiàng)目初始化
- $ git init best-cps && cd best-cps
- $ lerna init
創(chuàng)建三個(gè) package
- $ lerna create LibA && lerna create LibB && lerna create BaseUI
創(chuàng)建的每個(gè)包的目錄結(jié)構(gòu)如下:
- LibA
- ├─ tests
- │ └─ dooring.test.js
- ├─ lib
- │ └─ dooring.js
- ├─ README.md
- └─ package.json
安裝對(duì)應(yīng)包的依賴(lài)
由上文展示的3個(gè)包的依賴(lài)關(guān)系, 我們需要針對(duì)性的安裝, 如下:
- $ lerna add LibA --scope=LibB
因?yàn)?LibB 依賴(lài) LibA, 所以我們使用 lerna add 時(shí)可以通過(guò) --scope 來(lái)指定安裝范圍. 再比如 BaseUI 同時(shí)依賴(lài)LibA, LibB 兩個(gè)包, 我們可以使用如下命令:
- $ lerna add LibA LibB --scope=BaseUI
剩下的我們都可以按照上述的方式進(jìn)行, 當(dāng)我們編寫(xiě)完對(duì)應(yīng)包的代碼后, 我們還可以使用:
- $ lerna publish
一鍵將包發(fā)布到 npm 上, 此處根據(jù)我們選擇的管理模式不同,所有 packages 的版本號(hào)都會(huì)根據(jù)lerna.json中的版本號(hào)進(jìn)行更新。但我們需要注意的是 lerna 版本更新支持兩種模式:
- 固定/鎖定模式(默認(rèn), 指定版本號(hào))
這種模式自動(dòng)將所有 packages 包版本捆綁在一起,對(duì)任何其中一個(gè)或者多個(gè) packages 進(jìn)行重大改動(dòng)都會(huì)導(dǎo)致所有 packages 的版本號(hào)進(jìn)行更新。
- 獨(dú)立模式(independent)
獨(dú)立模式,init的時(shí)候需要設(shè)置選項(xiàng)--independent。這種模式允許使用者對(duì)每個(gè)package單獨(dú)改變版本號(hào)。每次執(zhí)行l(wèi)erna publish的時(shí)候,針對(duì)所有有更新的package,會(huì)逐個(gè)詢(xún)問(wèn)需要升級(jí)的版本號(hào),基準(zhǔn)版本為它自身的package.json里面的版本號(hào)。這種情況下,lerna.json的版本號(hào)不會(huì)變化, 默認(rèn)為independent。我們可以在 lerna 初始化時(shí)指定:
- lerna init --independent
具體的案例可以參考: https://github.com/MrXujiang/best-cps
如何高效低成本的搭建簡(jiǎn)單易用的組件文檔
對(duì)于組件文檔, 市面上也有很多開(kāi)源的工具, 比如 vue-press, storybook, docz等, 因?yàn)槲易罱捻?xiàng)目多為 react, 這里我使用的是 dumi. 之前在分享實(shí)現(xiàn)滑動(dòng)驗(yàn)證碼組件的時(shí)候已經(jīng)和大家分享的 dumi的使用, 大家可以參考我之前的文章:
- 從零開(kāi)發(fā)一款輕量級(jí)滑動(dòng)驗(yàn)證碼插件
以下是在 lerna 項(xiàng)目中集成 dumi 后的文檔站點(diǎn)效果:
如何配置eslint代碼規(guī)范和代碼提交規(guī)范
eslint 代碼規(guī)范我想每個(gè)朋友都不陌生, 我們只需要安裝對(duì)應(yīng)的插件并編寫(xiě)對(duì)應(yīng)規(guī)則的配置文件即可, 這里舉一個(gè)簡(jiǎn)單的例子:
- // .eslintrc.js
- module.exports = {
- extends: [require.resolve('@umijs/fabric/dist/eslint')],
- rules: {
- 'import/no-extraneous-dependencies': 0,
- 'import/no-unresolved': 0,
- },
- };
配置好之后我們需要設(shè)置檢測(cè)時(shí)機(jī), 比如說(shuō)時(shí)運(yùn)行時(shí)檢測(cè)還是提交時(shí)檢測(cè), 由于個(gè)人習(xí)慣和效率問(wèn)題, 我采用了提交時(shí)檢測(cè), 也就是當(dāng)開(kāi)發(fā)者功能開(kāi)發(fā)完成, 執(zhí)行 git commit 的時(shí)候進(jìn)行檢測(cè), 我們可以利用 githook 來(lái)做預(yù)提交檢測(cè), 這里需要在 package.json 文件中添加如下命令:
- "gitHooks": {
- "pre-commit": "npm run lint:js"
- },
配置好之后我們隨便寫(xiě)一行不合規(guī)范的代碼, 然后提交, 終端會(huì)顯示如下信息:
從控制臺(tái)可以發(fā)現(xiàn)代碼不合規(guī)范的位置和原因, 如果我們沒(méi)有做出調(diào)整, 代碼就無(wú)法提交, 通過(guò)這樣的方式可以提高代碼質(zhì)量和出錯(cuò)概率, 非常有長(zhǎng)遠(yuǎn)價(jià)值.
同時(shí)上面提到了 githooks, 對(duì)于 githooks 的知識(shí)也非常有意思, 它可以幫我們?cè)诖a提交的不同階段進(jìn)行自定義操作, 比如代碼提交前的檢測(cè), 代碼提交信息規(guī)范等進(jìn)行校驗(yàn), 常用的 gtihooks 有:
- pre-commit
- prepare-commit-msg
- commit-msg
- post-commit
- pre-rebase
- post-merge
- pre-receive
- update
大家感興趣的可以訪(fǎng)問(wèn) https://githooks.com 獲取更多有關(guān) githooks的內(nèi)容.
對(duì)于代碼提交規(guī)范, 我們也需要做統(tǒng)一管理, 這樣能讓團(tuán)隊(duì)更直觀的知道每一次提交的內(nèi)容是什么, 尤其是多人協(xié)作的時(shí)候. 以下是幾個(gè)常見(jiàn)的提交不規(guī)范的例子:
- git commit -m '添加彈窗'
- git commit -m ':update 更新'
- git commit -m 'fix 修復(fù)一個(gè)bug'
之所以會(huì)存在以上提交格式不統(tǒng)一或者提交信息難懂的問(wèn)題, 都是因?yàn)槿鄙倭艘?guī)范的制約, 所以說(shuō)對(duì)于大型項(xiàng)目或者多人協(xié)作的項(xiàng)目, 最好還是統(tǒng)一規(guī)范, 這樣能提前避免很多不必要的麻煩.
要想實(shí)現(xiàn)對(duì)工程師提交信息的檢測(cè), 需要用到 commit-msg 這個(gè) githooks, 具體配置如下:
- "gitHooks": {
- "pre-commit": "npm run lint:js",
- "commit-msg": "node ./commitlint.js verify-commit"
- }
剩下的就是 commitlint.js 做的事情了, 它是我編寫(xiě)的一個(gè) nodejs 腳本, 用來(lái)檢測(cè)用戶(hù)提交的信息是否規(guī)范, 當(dāng)然大家也可以基于這個(gè)腳本定義自己的提交規(guī)范, 具體效果如下:
我們可以看到, 當(dāng)我們提交了一個(gè)不符合規(guī)范的信息之后, 終端控制臺(tái)會(huì)打印如下提示信息并終止程序繼續(xù)進(jìn)行.
通過(guò)以上的配置, 團(tuán)隊(duì)不同成員的寫(xiě)的代碼和提交信息都會(huì)非常統(tǒng)一和規(guī)范, 項(xiàng)目整體的質(zhì)量也會(huì)得到一定的提升.
以上基于 lerna + dumi + eslint + commit 實(shí)踐我已經(jīng)發(fā)布到 github, 大家可以參考學(xué)習(xí)一下, 歡迎提出更好的建議.
文章名稱(chēng):Lerna+Dumi+Eslint多包管理實(shí)踐
鏈接URL:http://m.fisionsoft.com.cn/article/coehhje.html


咨詢(xún)
建站咨詢(xún)
