成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

基于 lerna 實(shí)現(xiàn) Monorepo 項(xiàng)目管理

開發(fā) 項(xiàng)目管理
Monorepo 是一種將多個(gè)項(xiàng)目代碼存儲(chǔ)在一個(gè)倉庫里的軟件開發(fā)策略。根據(jù)筆者經(jīng)驗(yàn),Monorepo 將顯著提升開發(fā)人員的愉悅度,所以趕緊搞起來吧!

[[434845]]

隨著團(tuán)隊(duì)建設(shè)以及相關(guān)業(yè)務(wù)的日益增長,越來越多的 NPM 包需要多人協(xié)同維護(hù),各個(gè)項(xiàng)目之間有關(guān)聯(lián),就不得不在多個(gè)編輯器之間切換,以及通過 npm link 來調(diào)試,開發(fā)的效率受到制約,那有沒有一種方式可以解決現(xiàn)在的痛點(diǎn)?答案就是 Monorepo!

在字節(jié)跳動(dòng)內(nèi)部的百科詞條中對于 Monorepo 的定義如下:

Monorepo 是一種將多個(gè)項(xiàng)目代碼存儲(chǔ)在一個(gè)倉庫里的軟件開發(fā)策略。

目前來講,Lerna 作為 JavaScript項(xiàng)目的多包管理器,已經(jīng)是比較成熟,并已被現(xiàn)代企業(yè)所驗(yàn)證,因此接下來將逐步搭建一個(gè)基于 Lerna[1] 的 Monorepo 管理環(huán)境,希望可以幫助大家在各司業(yè)務(wù)中落地并實(shí)現(xiàn)降本提效。

根據(jù)筆者經(jīng)驗(yàn),Monorepo 將顯著提升開發(fā)人員的愉悅度,所以趕緊搞起來吧!

本文主要內(nèi)容結(jié)構(gòu)如下,朋友們可按需食用:

一、為什么選擇 Lerna

Monorepo 能被定義為策略,那么一定是一種能夠解決問題的方案,基于 Lerna 實(shí)現(xiàn)的 Monorepo 多包管理方式,能解決的問題(優(yōu)點(diǎn))如下:

  1. 扁平:同一倉庫(項(xiàng)目)下,統(tǒng)一管理維護(hù)多個(gè) package
  2. 集中:在根目錄的 node_modules/ 文件夾下維護(hù)所有 package 的三方依賴
  3. 簡化:根據(jù)文件變動(dòng)統(tǒng)一執(zhí)行命令,按需發(fā)包,自動(dòng)升級(jí)版本并回寫倉庫、打 tag
  4. 高效:有互相依賴的項(xiàng)目直接可直接關(guān)聯(lián),避免開發(fā)人員在多倉庫之間切換

當(dāng)然,Lerna 經(jīng)過長時(shí)間的使用,一些問題也在生產(chǎn)環(huán)境中暴露出來,典型的如:

  1. 無效構(gòu)建:每次發(fā)包前會(huì)對所有的 package 進(jìn)行構(gòu)建
  2. 無效依賴:每次發(fā)包都會(huì)安裝所有 package 的依賴項(xiàng)
  3. 幽靈依賴:Phantom dependencies[2] 在依賴提升(hoist)后更加明顯

這里將問題羅列出來,不是說 Lerna 就應(yīng)該被放棄,而是我們應(yīng)當(dāng)清楚技術(shù)方案的利與弊,并結(jié)合項(xiàng)目的實(shí)際情況做一些取舍,上述的缺點(diǎn)只是在構(gòu)建中不那么優(yōu)雅,但并不影響 Lerna 作為一種可落地 Monorepo 的方案。

二、初始化一個(gè) Monorepo 形式的項(xiàng)目

我們將從 0 到 1 構(gòu)建一個(gè)純凈的、基于 Lerna 的 Monorepo 項(xiàng)目,并將利于團(tuán)隊(duì)協(xié)作規(guī)范的 ESlint 校驗(yàn),Prettier 自動(dòng)格式化,以及 git commit message 規(guī)范一并完善。

2.1 初始化項(xiàng)目結(jié)構(gòu)

首先就是得全局安裝 Lerna:

  1. yarn global add lerna 
  2. // or 
  3. npm install lerna -g 

然后就是新建項(xiàng)目目錄,并使用 Lerna 初始化一個(gè)基本結(jié)構(gòu)

  1. mkdir dyboy-lerna-project 
  2. cd dyboy-lerna-project/ 
  3. lerna init --independent 

如此之后,便得到了如下的一個(gè)文件目錄結(jié)構(gòu):

  1. ├── lerna.json   // lerna 的配置文件 
  2. ├── package.json // 當(dāng)前項(xiàng)目的描述文件 
  3. └── packages/    // 存放所有包的文件夾 

Lerna 初始化項(xiàng)目的時(shí)候,追加了一個(gè) --independent 的參數(shù),其含義是使用獨(dú)立模式。

在 Lerna 中,有兩種模式:

  1. 固定模式:所有 package 的版本號(hào)保持一致,每次更新發(fā)包都是全量的
  2. 獨(dú)立模式:每個(gè) package 版本號(hào)各自獨(dú)立,互不影響,每次更新按需發(fā)包

一般我們都會(huì)選擇獨(dú)立模式,來避免多 package 下頻繁發(fā)包的情況出現(xiàn),尤其是在一些業(yè)務(wù)變化頻繁的項(xiàng)目下,發(fā)包壓力恐怖如斯😱。

2.2 Lerna + Yarn Workspaces

Lerna 默認(rèn)會(huì)使用 NPM 作為包管理器,但使用 yarn 作為 Lerna 的默認(rèn)包管理器是更推薦的方式。

在 Yarn 1.0 版本,就已經(jīng)支持了 workspaces 功能,其優(yōu)勢以及和 Lerna 的關(guān)系可以參考當(dāng)時(shí)的這篇文章:《Workspaces[3]》

Yarn Workspaces 相結(jié)合,使得 Lerna 方案補(bǔ)齊短板,如虎添翼。

首先是修改 lerna.json 配置,改為如下內(nèi)容:

  1. {  
  2.   "version""independent"
  3.   "npmClient""yarn"
  4.   "useWorkspaces"true 

然后在 package.json 文件中指明(新增)workspaces(工作空間)字段:

  1. "workspaces": ["packages/*"], 

意思就是認(rèn)為 packages/ 目錄下的所有項(xiàng)目都?xì)w Lerna + Yarn 管理,這之后,無論我們在哪個(gè)文件夾下執(zhí)行 yarn 都將分析 packages/ 目錄下所有項(xiàng)目的依賴,并安裝到根目錄的 node_modules/ 中。

2.3 ESlint + Prettier + Commit Rules

針對項(xiàng)目需要配置上述的規(guī)則,在任一項(xiàng)目中來說都是比較統(tǒng)一的,因之前文章中詳述過相關(guān)配置流程,此處便不再贅述。

相關(guān)配置規(guī)則的初始化和詳細(xì)流程可參考:《手摸手學(xué)會(huì)搭建一個(gè) TS+Rollup 的初始開發(fā)環(huán)境》中第 5~7 步驟。

經(jīng)過上述配置好之后,我們的項(xiàng)目就算是大致初始化完成了!

2.4 NPM 團(tuán)隊(duì)賬號(hào)

因?yàn)榘l(fā)包需要賬號(hào),Monorepo 同時(shí)管理了數(shù)個(gè)、數(shù)十個(gè)包,都需要維護(hù)發(fā)包。

如果使用個(gè)人賬號(hào)發(fā)包到公司內(nèi)自建的 Registry 上,萬一該同學(xué)離職了,該倉庫會(huì)變成“幽靈倉庫”。

當(dāng)然,我們可以找公司內(nèi)部 Registry 維護(hù)者直接更改對應(yīng)包,但總歸是比較麻煩的一件事。

為此可以給團(tuán)隊(duì)申請一個(gè)公共賬號(hào),通過 npm token create 創(chuàng)建一個(gè)權(quán)限 token,放到項(xiàng)目根目錄下的 .npmrc 文件中。

之后無論是哪個(gè)開發(fā)者維護(hù),都將默認(rèn)使用團(tuán)隊(duì)賬號(hào)發(fā)包更新。

最后初始化的項(xiàng)目文件結(jié)構(gòu)如下:

三、版本發(fā)布

之前說到過,Lerna 可以統(tǒng)一管理所有的包,因此我們可直接在根目錄的 package.json 文件中指定快捷指令,實(shí)現(xiàn)按需發(fā)包的功能

注意: Lerna 發(fā)包時(shí),會(huì)默認(rèn)忽略掉在 package.json 中設(shè)置了 "private": true 的私有包。

3.1 項(xiàng)目打包編譯

在發(fā)新的包版本之前,一般是需要打包編譯好產(chǎn)物,在 Monorepo 下的多個(gè)包發(fā)布前,肯定也是需要先打包。

(1). Learn Run

借助 Lerna 提供的 run 命令,可以實(shí)現(xiàn)在發(fā)包前,讓所有在 package.json -> scripts 中定義了指令的項(xiàng)目執(zhí)行該命令

例如,執(zhí)行:lerna exec build

則會(huì)遍歷每一個(gè) package,尋找其 package.json -> scripts 中是否定義了 build 命令,有則執(zhí)行,否則跳過(在所有包含 build 命令的包中運(yùn)行 npm run build)。

這樣的方式會(huì)存在一個(gè)問題:每次發(fā)包前,都會(huì)把所有 pckage 都先 build 了一遍,增加了打包發(fā)布的時(shí)間。

那有沒有更優(yōu)雅的方式吶?

(2). NPM Scripts 生命周期

在 package.json 文件中自定義的 scripts 字段,含有默認(rèn)的兩個(gè)生命周期 pre 和 post

通過執(zhí)行 npm run build,則會(huì)先自動(dòng)執(zhí)行npm run prebuid,然后是 npm run build,再者是執(zhí)行 npm run postbuild。

除了 package.json -> scripts 中自定義的命令,還有 npm 自帶的一些 scripts,比如 npm publish。

npm publish 命令的生命周期包含:

  1. prepublishOnly
  2. prepare
  3. prepublish
  4. publish
  5. postpublish

prepare 在 npm publish --dry-run 時(shí)不會(huì)被執(zhí)行。

注意:npm 6.x 和 7.x 版本的生命周期有不同,上面是 6.x 版本,考慮到 6.x 和 7.x 版本的差異,建議將發(fā)包前的動(dòng)作放到 prepublishOnly 命令中。

更多可以參考:《scripts - NPM 6.x 官方文檔[4]》 & 《scripts - NPM 7.x 官方文檔[5]》

(3). 按需 Build

有了上面對于 NPM Publish 生命周期的基礎(chǔ),因此我們可以在需要在發(fā)包時(shí)候構(gòu)建的項(xiàng)目(packages/目錄下的項(xiàng)目),在其 package.json -> scripts 中定義如下字段:

  1. "scripts": { 
  2.     "build""rollup -c"
  3.     "prepublishOnly""yarn build" 

如此,在執(zhí)行 npm publish 的時(shí)候,會(huì)先執(zhí)行 prepublishOnly 中的 yarn build,項(xiàng)目編譯打包,然后再發(fā)包。

如此,按需發(fā)包就可以很優(yōu)雅、流暢地搞定了!

3.2 項(xiàng)目發(fā)包

到了發(fā)包階段,我們在根目錄的 package.json 文件中添加內(nèi)容:

  1. "scripts": { 

  2.   "release""lerna publish"
  3.   "release:beta""lerna publish --canary --pre-dist-tag=beta --preid beta --yes" 
  4. }, 

yarn release 用于發(fā)布正式版

yarn relase:beta 則是用于發(fā)布測試版本,用于給開發(fā)聯(lián)調(diào)時(shí)候測試使用

約定大于配置:在根目錄下的 package.json -> name 字段默認(rèn)為 root,大家可以理解為“工作根目錄”,如果是有作用域的(scope,例如:@dyboy/utils),可以改名為:@dyboy/root,以便于讓其他開發(fā)者知道這是一個(gè)有作用域的 Monorepo 項(xiàng)目,盡管 name 字段并沒有什么作用。

總結(jié)

基于 Lerna 構(gòu)建的 Monorepo 項(xiàng)目的心智成本不高,但需要我們對于其中的流程、生命周期、NPM Scripts 等知識(shí)有一定的認(rèn)識(shí)和把握,需要構(gòu)建者能在流程、管理中尋找需求共性和約束規(guī)范,為團(tuán)隊(duì)的降本提效落地解決方案。

本文從根據(jù)搭建流程來簡述 Monorepo 的一種方案,在前端工程化中,構(gòu)建者還需要思考是否存在優(yōu)化空間以及斟酌細(xì)節(jié)?比如,書寫通俗易懂的 README.md 文檔,思考是否能讓新人更容易上手,嘗試解決流程中的問題并積極探索新的 Monorepo 技術(shù)解決方案,比如 Rush、PNPM ...

TODO: 能否實(shí)現(xiàn) Monorepo 自動(dòng)發(fā)正式版本的包?感興趣的朋友可以關(guān)注后續(xù)的分享嗷!

參考資料

[1]Lerna 官方網(wǎng)站: https://lerna.js.org/

[2]Phantom dependencies - 應(yīng)用級(jí) Monorepo 優(yōu)化方案: https://github.com/worldzhao/blog/issues/9

[3]Yarn Workspaces: https://classic.yarnpkg.com/lang/en/docs/workspaces/

[4]scripts - NPM 6.x 官方文檔: https://docs.npmjs.com/cli/v6/using-npm/scripts

[5]scripts - NPM 7.x 官方文檔: https://docs.npmjs.com/cli/v7/using-npm/scripts

 

責(zé)任編輯:姜華 來源: DYBOY
相關(guān)推薦

2024-05-30 09:07:20

2021-10-05 21:56:43

管理Dumi Eslint

2023-08-23 18:56:46

2023-12-07 07:02:00

大倉權(quán)限設(shè)計(jì)

2024-03-21 15:07:22

2023-07-12 20:12:57

前端Monorepo代碼

2020-12-28 05:56:57

Monorepo代碼庫工具

2025-01-13 07:15:00

Monorepo代碼倉庫中項(xiàng)目代碼管理

2022-07-20 10:01:23

MonorepoReact

2010-02-26 15:09:59

Linux NFS

2019-08-22 09:55:17

RedisAPI數(shù)據(jù)

2024-10-06 12:35:50

2015-03-09 10:33:14

即時(shí)通信管道過濾

2022-09-13 15:33:48

KubeEdge邊緣計(jì)算容器

2016-09-29 15:44:18

開源上網(wǎng)管理

2021-03-25 09:41:43

前端Monorepo技術(shù)熱點(diǎn)

2010-06-01 09:33:48

SVN創(chuàng)建管理項(xiàng)目

2022-09-22 09:54:56

技術(shù)選型

2022-07-28 10:46:16

開放策略代理引擎
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 九九久久这里只有精品 | 91久久精品一区二区二区 | 中文字幕高清视频 | 在线免费视频一区 | aaa大片免费观看 | 国产激情视频在线 | 黑人精品xxx一区一二区 | 男女羞羞视频免费 | 欧美日韩精品国产 | 午夜激情国产 | 国产精品久久久久久久久久久久 | 亚洲精品免费在线观看 | 亚洲色图插插插 | 高清亚洲 | 精品一区二区免费视频 | 欧美人成在线视频 | 国产高清精品一区二区三区 | av片在线观看网站 | 在线观看中文字幕一区二区 | 成人a免费 | 欧美九九九| 九九热在线免费观看 | 成人在线一区二区 | 国产 亚洲 网红 主播 | 一区二区在线免费播放 | 日韩国产欧美视频 | 人人干视频在线 | 99精品视频在线观看免费播放 | 激情久久网 | 成人免费在线播放视频 | 欧美视频精品 | 99福利视频| 国产99久久精品一区二区300 | 亚洲国产黄 | 日韩视频中文字幕 | 97视频在线免费 | 911精品美国片911久久久 | 国产精品mv在线观看 | 国产亚洲一区二区三区在线 | 国产乱一区二区三区视频 | 亚洲欧美综合网 |