規(guī)范升級(jí) NPM 包

規(guī)范升級(jí) NPM 包
前言
在日常工作中,當(dāng)組件跨項(xiàng)目使用時(shí),我們往往會(huì)選擇把組件抽成 npm 包。那么在 npm 開發(fā)以及發(fā)布的過程中有什么需要注意的事項(xiàng)嗎?本文將從我自己的角度,來(lái)為大家介紹一下我認(rèn)為的一些需要大家注意的點(diǎn)。
版本號(hào)規(guī)則
從日常的開發(fā)中我們可以看到,npm 包的版本號(hào)的格式都是 X.Y.Z。那么大家發(fā)布的 npm 包為什么都在遵循這個(gè)格式呢?這個(gè)格式其實(shí)是由 Gravatars 創(chuàng)辦者兼 GitHub 共同創(chuàng)辦者 [Tom Preston-Werner] http://tom.preston-werner.com/ 所建立。由 GitHub 起草的統(tǒng)一的版本號(hào)表示規(guī)則,稱為 Semantic Versioning (語(yǔ)義化版本表示)。這些規(guī)范具體包含的內(nèi)容大家可以參考[語(yǔ)義化版本 2.0.0] https://semver.org/lang/zh-CN/ 本文只針對(duì)我們開發(fā)中容易忽略的地方做一些詳述。
X 代表主版本號(hào),也叫做大版本號(hào)
升級(jí)大版本時(shí)意味著這個(gè)包可能做了顛覆性的改動(dòng),和低版本的包已經(jīng)無(wú)法兼容。每當(dāng)主版本號(hào)遞增時(shí),次版本號(hào)和修訂號(hào)必須歸零。
Y 代表次版本號(hào),也叫做小版本號(hào)
當(dāng)做了向下兼容的功能性新增時(shí),升級(jí)小版本號(hào)。每當(dāng)次版本號(hào)遞增時(shí),修訂號(hào)必須歸零。
Z 代表修訂號(hào)
當(dāng)做了向下兼容的問題修正(bugfix)時(shí), 升級(jí)修訂號(hào)。
常見版本格式/引用方式
| 版本引用方式 | 版本號(hào) | 匹配版本 | 解釋 |
| 直接使用版本號(hào) | 2.3.1 | 2.3.1 | 只可以匹配 2.3.1 這個(gè)版本,如果是比較重要的項(xiàng)目,建議用這種方式固定版本。 |
| ^:不能修改版本號(hào)最左側(cè)非零數(shù)字 | ^2.3.1 | >= 2.3.1 && < 3.0.0 | 最左側(cè)非零數(shù)字是 2 |
| ^0.3.1 | >= 0.3.1 && < 0.4.0 | 最左側(cè)非零數(shù)字是 3 | |
| ^0.0.1 | >= 0.01 && < 0.02,即 0.01 | 最左側(cè)非零數(shù)字是 1 | |
| ~:版本號(hào)列出 Y 時(shí)兼容 Z 的修改。列出 X 時(shí)兼容 Y、Z | ~2.3.1 | >= 2.3.1 && < 2.4.0 | Y 為 3。~2.3 同理 |
| ~2 | >= 2.0.0 && < 3.0.0 | X 為 2 | |
| *、X、x,空:表示可以匹配任何版本 | "2.3.X"、"2.3.x"、"2.3*"、"2.3" | >= 2.3.0 && < 2.4.0 | Z 可以為任意值 |
| "2.X"、"2.x"、"2.*"、"2" | >= 2.0.0 && < 3.0.0 | Y、Z 為任意值 | |
| *、X、x,空 | 任意版本 | 任意版本指的是最新的正式版 |
關(guān)于 npm 的版本格式還有許多,此處不再贅述。
從上邊的常用格式介紹可以看出來(lái),在精確版本號(hào)的情況下,版本號(hào)是完全固定的,在項(xiàng)目發(fā)布時(shí)不會(huì)出現(xiàn)一些實(shí)際安裝的包和 package.json 中版本號(hào)不一致的問題。或者如果使用方有用到 package-lock.json 文件來(lái)固定包的版本,也可以避免包的版本號(hào)導(dǎo)致的問題。
但是在實(shí)際開發(fā)中,我們并不知道我們包的使用方是否使用的固定版本號(hào)或者 package-lock.json 文件,我們?cè)趺醋霾拍茏屖褂梅讲皇苡绊懩兀?/p>
這時(shí)候就要用到先行版本號(hào)了,下面我將為大家具體介紹。
先行版本
npm 的先行版本號(hào),放到 X.Y.Z 的后邊,作為延伸。被標(biāo)上先行版本號(hào)則表示這個(gè)版本并非穩(wěn)定而且可能無(wú)法滿足預(yù)期的兼容性需求。例如:1.0.0-alpha.1,2.0.0-beta.1 等。一般常用的關(guān)鍵詞有:
alpha:預(yù)覽版,或者叫內(nèi)部測(cè)試版;一般不向外部發(fā)布,會(huì)有很多 bug(會(huì)不太穩(wěn)定);一般只有測(cè)試人員使用。 beta:測(cè)試版,或者叫公開測(cè)試版;這個(gè)階段的版本會(huì)一直加入新的功能;在 alpha 版之后推出。 rc(release candidate):最終測(cè)試版本;可能成為最終產(chǎn)品的候選版本,如果未出現(xiàn)問題則可發(fā)布成為正式版本。
先行版本升級(jí)規(guī)則
我們使用 npm dist-tag ls @zcy/zcy-region-detail-back 查看 @zcy/zcy-region-detail-back 的 tag,如下:

我們可以看到這個(gè)包有一個(gè) beta 版,一個(gè) latest 版。
對(duì)比兩個(gè)版本的名字可以發(fā)現(xiàn),beta 版本是在 latest 版本的 Z 上加了 1 且添加了一個(gè) beta 作為延伸。
如果包只是對(duì)現(xiàn)有的問題進(jìn)行修復(fù),那么只需要對(duì) Z 進(jìn)行加 1,然后添加延伸。 如果包本次是做向下兼容的功能性新增,那么需要對(duì) Y 進(jìn)行加 1,Z 清零,然后添加延伸。 如果包本次的升級(jí)是無(wú)法向下兼容的,那么就需要對(duì) X 進(jìn)行加 1,Y、Z 清零,然后添加延伸。
如果在加了延伸的版本上需要進(jìn)行 bugfix 時(shí),只需要將我們延伸的版本繼續(xù)增加即可。當(dāng) bugfix 結(jié)束,需要發(fā)布正式版本時(shí),只需要去掉延伸版本,發(fā)布版本即可。
什么時(shí)候需要使用先行版本
假設(shè) P 項(xiàng)目中引用了 @zcy/zcy-region-detail-back 包,如下:

A 需求改動(dòng)了項(xiàng)目 P,發(fā)布時(shí)間為 6.30。
B 需求改動(dòng)了 @zcy/zcy-region-detail-back 包,改動(dòng)的時(shí)間是 6.29。
B 需求的改動(dòng)沒有使用先行版本且包中的 bug 在 6.30 項(xiàng)目 P 發(fā)布時(shí)沒有修改。此時(shí)就會(huì)導(dǎo)致項(xiàng)目 P 發(fā)布時(shí),下載到了有 bug 的 @zcy/zcy-region-detail-back 包,就會(huì)導(dǎo)致線上問題。
這是因?yàn)槲覀冊(cè)?P 項(xiàng)目中執(zhí)行 npm i @zcy/zcy-region-detail-back 后,下載出來(lái)的 @zcy/zcy-region-detail-back 的版本號(hào)為 1.0.0。因?yàn)樵趫?zhí)行 npm i @zcy/zcy-region-detail-back 時(shí)會(huì)默認(rèn)下載 tag 為 latest 下的最新包。相當(dāng)于執(zhí)行了 npm i @zcy/zcy-region-detail-back@latest。注:這里的 tag 指的是 npm 中的 tag。

所以 npm 的 tag 到底有什么用呢?其實(shí) tag 就相當(dāng)于是 git 的分支管理中的標(biāo)簽,不同的 tag 之間的包互不影響。可以使我們發(fā)布先行版本時(shí)不影響正式版本。
一般常用的有三種類型的 tag:
latest:最后的穩(wěn)定版,npm install 時(shí)就是下載的這個(gè) beta:測(cè)試版本,需要指定版本或者使用 npm install packageName@beta來(lái)下載。例如:1.0.0-beta.0next:先行版本,使用 npm install packageName@next安裝
版本發(fā)布
那么我們?nèi)绾伟l(fā)布先行版本的包呢?首先需要升級(jí) A 包的版本號(hào),此處介紹兩種升級(jí)方式
方式一:簡(jiǎn)單粗暴,手動(dòng)修改 package.json 中的 version:

這種方式需要我們自己手動(dòng)執(zhí)行 git commit -am 'XXXX' 提交代碼,如果需要在此版本的 git 倉(cāng)庫(kù)打上 tag 時(shí),需要我們自己手動(dòng)觸發(fā)git tag v2.3.2-beta.1 ,git push origin v2.3.2-beta.1 。
方式二:借助 npm version 命令
A 包中所有的改動(dòng)都 commit 后,可以根據(jù)以下命令更新版本
npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]
// newversion:指定更新的版本號(hào)
// major:大版本并且不向下兼容時(shí),使用 major
// minor:有新功能且向下兼容時(shí),使用 minor
// patch:修復(fù)一些問題、優(yōu)化等,使用 patch
// 以 A:2.3.1 為例
npm version premajor // 版本號(hào)會(huì)成為 3.0.0-0,即 3.0.0 的預(yù)發(fā)版本
npm version preminor // 版本號(hào)為成為 2.4.0-0,即 2.4.0 的預(yù)發(fā)版本
npm version prepatch // 版本號(hào)成為 2.3.2-0,即 2.3.2 的預(yù)發(fā)版本
/**
* 版本號(hào)會(huì)成為 2.3.2-0。
* 執(zhí)行此命令時(shí),如果沒有預(yù)發(fā)布版本號(hào),則增加 Z,增加預(yù)發(fā)布號(hào)為 0
* 如果有預(yù)發(fā)步號(hào),增加預(yù)發(fā)步號(hào)
*/
npm version prerelease
根據(jù)上邊的 API 可以看到我們能通過 npm version 2.3.2-beta.1 將 A 的版本升為 2.3.2-beta.1 的形式,除此之外,在 npm 6.4.0 之后,我們也可以使用 --preid 參數(shù)來(lái)添加前綴:
npm version prerelease --preid=beta
此種方式需要注意,必須要 commit 本地的修改之后才可以執(zhí)行。npm version 修改版本號(hào),會(huì)默認(rèn)執(zhí)行 git add -> git commit -> git tag 操作,此時(shí)的版本號(hào)看起來(lái)有 beta,如下:

但是這個(gè) beta 是 git 倉(cāng)庫(kù)的 tag,并不是 npm 的 tag。如果不想默認(rèn)給 git 添加 tag 的話,可以使用以下命令:
npm --no-git-tag-version version xxx
那么 npm version 執(zhí)行時(shí)具體發(fā)生了什么呢?簡(jiǎn)要流程圖如下

執(zhí)行完 npm version 2.3.2-beta.1 之后,如果直接使用 npm publish 來(lái)發(fā)布的話,發(fā)布出來(lái)的包的 tag 是 latest,但是我們其實(shí)是想發(fā)布一個(gè)測(cè)試包。如果其他人 npm i 下載時(shí)就會(huì)下載 version 為 2.3.2-beta.1 的包。只有使用 npm publish --tag XXX 才是給 npm 包上打了 tag 標(biāo)簽。
執(zhí)行以下命令就可以生成一個(gè) tag 為 beta 的包:
npm run build // 打包
npm publish --tag beta // 發(fā)布 beta 包

如果不小心直接使用 npm publish 發(fā)錯(cuò)了也沒有關(guān)系,可以使用以下命令來(lái)添加 tag:
npm dist-tag add <pkg>@2.3.2-beta.1 <tag>
當(dāng)需要?jiǎng)h除多余的 tag 時(shí):
npm dist-tag rm <pkg> <tag>
給大家提供一條指令完成 beta 版本的發(fā)布:
"scripts": {
"publish:beta": npm version prerelease --preid=beta && npm run build && npm publish --tag=beta"
},
代碼開發(fā)完畢,提交之后,只需要 npm run publish:beta 就可以發(fā)布一個(gè)測(cè)試版本啦~
以上就是我本次分享的所有內(nèi)容啦,如果有不足的地方,還望指正。
參考文獻(xiàn)
語(yǔ)義化版本 2.0.0 (https://semver.org/lang/zh-CN/spec/v2.0.0.html)
前端工程化(5):你所需要的 npm 知識(shí)儲(chǔ)備都在這了(https://juejin.cn/post/6844903870578032647)
npm version (https://docs.npmjs.com/cli/v6/commands/npm-version)

往期推薦



最后
歡迎加我微信,拉你進(jìn)技術(shù)群,長(zhǎng)期交流學(xué)習(xí)...
歡迎關(guān)注「前端Q」,認(rèn)真學(xué)前端,做個(gè)專業(yè)的技術(shù)人...


