深刻 Node 模塊的安裝和發佈

npm 是一個方便的 Node 模塊分發、管理工具。咱們日常會使用 npm install 安裝模塊,使用 npm publish 發佈模塊。事實上除了基本功能,這 2 個命令還有其餘很是有用的特性。這篇文章會給你們介紹這些命令的一些「高級」用法。javascript

模塊的版本號

咱們先來講說版本號。npm 使用的是一種叫作 semantic version 的規範,它的規則很簡單,總結起來就是下面幾條:java

  • 使用 semver 的軟件必須定義公開、嚴謹、易於理解的 API。也就是模塊要提供功能給用戶。node

  • 版本號格式爲:X.Y.Z,而且 X、Y、Z 均爲正整數而且不斷遞增。X 表示大版本(major)、Y 表示小版本(minor)、Z 表示補丁版本(patch)。git

  • 一個版本發佈後,此版本內容不能再變動,變動必須再發佈一個新版本。也就是不能覆蓋發佈。github

  • 0.Y.Z 表示初始版本,這種版本下的 API 不能保證穩定,隨時可能變動。npm

  • 當進行了向後兼容的 bug 修復時,補丁版本 Z 必須增長。json

  • 當引入了向後兼容的新功能時,小版本 Y 必須增長,同時 Z 必須重置爲 0(小版本里面可能會包含 bug 修復)。promise

  • 當引入了不兼容的變動時,大版本 X 必須增長,同時 Y、Z 必須重置爲 0(大版本里面可能會包含小版本或者補丁版本的改動)。koa

  • X.Y.Z 後面還能夠加預發佈版本號、構建信息,格式爲:X.Y.Z-pre_lease+build_meta,好比:1.0.0-alpha+201512261.0.0-beta.2+20151230工具

  • 進行版本號比較時,遵循下面的規則:1)依次按數值比較 X、Y、Z 的值,直到第一個不一樣的位置;2)若是兩個版本的 X、Y、Z 都相等,含有 pre-release 版本號的較小;3)若是兩個版本的 X、Y、Z 都相等而且都含有 pre-release 版本號,要單獨比較 pre-release 版本。好比:1.0.0 < 2.0.0 < 2.1.0 < 2.1.11.0.0-alpha < 1.0.01.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2

模塊的依賴管理

在進行項目開發時,對於依賴的模塊進行管理是很是必要的。這種管理主要體如今:

  1. 如何方便的獲取項目須要使用的模塊

  2. 當前項目依賴了哪些模塊,或許還會指定模塊依賴的環境(哪些模塊是生產階段依賴的、哪些是開發階段依賴的)

  3. 模塊的哪些版本是和當前項目兼容的,能夠直接使用

  4. 其餘成員(或者系統)如何方便的獲取全部模塊,從而能讓項目正常運行

下面咱們看看 npm 是如何幫助咱們解決上面這些問題的。

獲取模塊

咱們在進行項目開發時,若是須要某個功能,都會先去 npm registry 上搜一搜,看看有沒有相似的模塊能夠直接複用,從而提升開發效率。獲取模塊很是簡單,咱們在項目的根目錄直接執行 npm install name 就能夠將模塊安裝在 node_modules 目錄下,而後直接 require 就可以使用。

依賴了哪些模塊

上面獲取模塊的方法是一種「臨時」起意的方式,並不能記錄咱們依賴模塊的具體信息(除非咱們本身去查找)。咱們安裝模塊時,能夠執行 npm install name --save(生產階段的依賴) 或是 npm install name --save-dev(開發階段的依賴),來將模塊信息保存到項目的 package.json 文件中。

模塊依賴表示法

執行 npm install name --save 來安裝模塊時,npm 會首先安裝模塊的最新版本,而後將模塊名及模塊版本號以最「保險」的表示方式寫入到 package.json 文件中。

好比,咱們執行 npm install koa --save,安裝模塊後,會更新package.json 文件的 dependencies 字段:

{
  "dependencies": {
    "koa": "~1.1.0"
  }
}

項目對模塊的依賴可使用下面的 3 種方法來表示(假設當前版本號是 1.1.0 ):

  1. 兼容模塊新發布的補丁版本:~1.1.01.1.x1.1

  2. 兼容模塊新發布的小版本、補丁版本:^1.1.01.x1

  3. 兼容模塊新發布的大版本、小版本、補丁版本:*x

能夠看到,npm 默認會將依賴表示爲最「保險」的方式(即:獲取模塊新發布的補丁版本),咱們也可使用 npm install koa --save-exact 來精確的指定模塊版本(這種狀況依賴就直接表示爲:"koa": "1.1.0")。

除了獲取模塊的最新版本,咱們還能夠精確獲取模塊的某個具體版本,如:npm install koa@1.0.0 --save,這種狀況依賴就會表示爲:"koa": "~1.0.0"

安裝模塊

模塊的依賴都被寫入了 package.json 文件,其餘合做者(好比:其餘小夥伴、或者是部署服務)只要進入項目的根目錄,執行 npm install 就能夠將依賴的模塊所有安裝到 node_modules 目錄下。

好比下面的 package.json

{
  "dependencies": {
    "bluebird": "~3.1.1",
    "request-promise": "^1.0.2",
    "lodash": "*"
  },
  "devDependencies": {
    "mocha": "~2.3.4"
  }
}

當咱們執行 npm install 時,就會安裝 dependenciesdevDependencies 字段裏列出的全部模塊。若是隻想安裝 dependencies 裏面列出的模塊,可使用 npm install --only=production

這裏 npm 實際安裝的模塊是根據依賴的表示來決定的:

  • "bluebird": "~3.1.1" 表示會安裝最新的補丁版本。好比:安裝 3.1.二、3.1.3 等,可是不會安裝 3.2.0 這種小版本或者4.0.0 這種大版本(就算這些版本是最新的)。這種表示法是比較保險的,由於補丁版本只是 bug 修復,不會新增功能。

  • "request-promise": "^1.0.2" 表示會安裝最新的補丁版本或者小版本。好比:安裝 1.1.0、1.1.1 等小版本,或者 1.0.三、1.0.4 等補丁版本,可是不會安裝 2.0.0 這種大版本。並且,老是安裝版本號最大的(也就是優先安裝小版本)。這種表示法一般是保險的,小版本會增長向後兼容的功能。

  • "lodash": "*" 表示安裝最新的版本(無論這個版本是大版本、小版本、仍是補丁版本)。這種表示法很是危險,若是有大版本,直接就安裝了大版本,而大版本一般是不會向後兼容的,可能致使項目功能運行異常。

模塊的發佈

對於模塊的提供者來講,每一次發佈都應該儘可能遵循 semver 的規範來變動版本號,不要讓用戶困惑甚至是想罵人......

在「模塊的版本號」部分咱們介紹了 semver 規範,npm 也提供了相關的命令來讓咱們方便的進行版本號變動:

  • 升級補丁版本號:npm version patch

  • 升級小版本號:npm version minor

  • 升級大版本號:npm version major

一個比較合適的發佈流程能夠是:

  • 根據這次變動執行 npm version [new version] 命令(npm 會根據 new version 指定的類型更新 package.json 中的 version 字段,而後進行一次 commit,最後打上一個該版本號的 tag)。

  • 執行 git push origin master --tags,將改動同步到遠程代碼倉庫。

  • 執行 npm publish,將模塊發佈到 npm 倉庫。

模塊的 tag

模塊安裝命令的最簡形式 npm install name 的完整版其實應該是:npm install name@latest。這裏的 latest 是模塊版本的一個 tag,會對應到模塊的一個具體版本。

咱們來看一個例子:模塊 koa 在 npm registry 上的信息以下(完整版見:http://registry.npmjs.com/koa):

{
  "name": "koa",
  "dist-tags": {
    "latest": "1.1.2",
    "next": "2.0.0-alpha.3"
  },
  "versions": {
    "0.0.1": {...},
    "1.1.2": {...},
    "2.0.0-alpha.3": {...}
  }
}

當執行 npm install koa 時,實際上是執行 npm install koa@latest,而這個 latest 等於 dist-tags.latest(版本 1.1.2),最後版本 1.1.2 被安裝,同時依賴會標記爲 "koa": "~1.1.2"

當執行 npm install koa@next 時, next 等於 dist-tags.next(版本 2.0.0-alpha.3),最後版本 2.0.0-alpha.3 被安裝,同時依賴會標記爲 "koa": "~2.0.0-alpha.3"

模塊的維護者在進行模塊發佈時,能夠指定將當前版本發佈爲哪一個 tag(默認是 latest)。

當執行 npm publish 時,會首先將當前版本發佈到 npm registry,而後更新 dist-tags.latest 的值爲新版本。

當執行 npm publish --tag=next 時,會首先將當前版本發佈到 npm registry,而且更新 dist-tags.next 的值爲新版本。這裏的 next 能夠是任意有意義的命名(好比:v1.x、v2.x 等等)。

能夠看出,tag 就是對模塊某一個版本的標記(類比 git 中 tag 是對某一次提交的標記),而且這個 tag 還能夠隨時更新爲新的版本號。

能對版本打 tag,使得咱們在維護多個版本時很是方便。好比,能夠像 koa 的作法同樣,新開一個 next 的 tag 來提供新版本給社區試用,而不影響如今的穩定版本。等到新版本逐漸穩定後,再將其發佈爲 latest 便可。

其餘問題

這樣看起來,發佈 Node 模塊是否是很簡單?其實,咱們沒有說的東西還有不少。好比下面這些問題:

每次發佈前怎麼保證模塊提供的功能沒有損壞?能夠考慮接入持續集成系統,每次 push 運行單元測試,未經過不進行發佈。

版本號其實對維護者不友好,很容易改錯,有沒有什麼好方法來解決?能夠考慮規範提交信息,維護者只是描述變動,從提交信息中抽取變動類型而後生成正確的版本號和變動日誌(好比:angular 的提交信息規範:https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit

這些問題要是能夠自動化多好!我嘗試搜索了下,果真有開發者在搞了。推薦你們看看這個工具:https://github.com/semantic-release/semantic-release,很好的解決了上面的問題。

可是其實最最核心的問題是維護者得養成好習慣(寫單測、規範提交信息),否則再好的工具都白搭。我也在慢慢培養中,真是痛苦......

參考資料

相關文章
相關標籤/搜索