在開發 Angular 專案的時候,碰到了跟版本號控制有關的任務,之前沒有認真探究不同位置的數字有什麼函義,就稍微研究了下 npm 上面的那些 packages 的三位數版本號還有符號 ^~ 代表什麼意思


概略

版本控制的存在是讓開發者每次更新軟體時,方便區別目前軟體狀態的管理方式,除了能識別現在 user 手上的軟體狀態,也助於團隊內 QA 在測試的時候,能明確告知現在是哪一版出了什麼問題

跟 git 做程式碼版控的概念很像,都是為了使軟體的開發流程更順暢的一種策略,只是 semantic 是用在發布的軟體上的更新,git 是針對每次程式碼的更新

軟體的版本號其實並沒有一個準則,都是以共識為主,而 semantic 提供了一個參考,用 X.Y.Z 三個數字來分別定義不同的更新狀態,npm 採用了他的準則

npm package

在使用 npm 做前端開發時,管理目前用到的軟體包標配就是 package.json,隨著開發的時間越長,專案內需要用的 library 就會越來越多

package.json 是一種管理軟體的格式,是 npm 制訂的一種規範,任何要透過 npm 發佈的軟體都得按照這個規範提供該軟體的基本資訊,像是名稱的長度,名稱的字符類型限制,還有要使用 @ 開頭等等

再來最重要的就是 version 的欄位,npm 規定要用 node-semver 來解析

semantic 版本號

semantic 定義了軟體版本用 X.Y.Z 的數字格式來管理

  • X = Major version
  • Y = Minor version
  • Z = Patch version

Major

做了不相容的修改,要遞增主要版號,通常最一開始的 1.0.0 是初發行版本(release),如果做了重大更新無法向後相容 (Backward compatible),semver 就會希望軟體更新為 2.0.0

Minor

做了目前主要版本的功能性更新,則需要遞增次要版本,比如 1.1.0,代表基於 1.0.0 的軟體狀態上,新增了能向後兼容的功能

Patch

故名思議就是修補的更新,做了目前主版本的 Bug 修正,則需要遞增修補版本,比如 1.0.1 代表基於 1.0.0 的軟體狀態上,新增了能向後兼容的修正

npm install 筆記

在使用 npm install 指令的時候,會根據目前專案底下的 package.json 列出的軟體來安裝到 node_modules,確保目前環境已經有這些相依的軟體存在

如果要安裝特定的軟體與版本,npm 提供了指令

1
npm install @<package-name>@<version>

要安裝特定軟體的最新版本則

1
npm install @<package-name>@latest

在 version 的參數,可以利用 semver 提供的 range syntax

Range syntax & prefix

如果在 version 數字前面上加了 ^ 前綴,代表目前 Major 版本不更新的狀態下,更新至最新,也就是 Minor & Patch 會遞增到目前最新的版本,比如 ^1.0.1,可能就會更新至 1.2.3,即使其實最新的版本已經到 2.?.?

如是 ~ 前綴,則代表更新 Patch level (Minor 版號被指定的狀態下),比如 ~1.0.1,可能就會更新到 1.0.6,但如果是寫像是 X-Range,~1.x.1,則 Minor 也會被更新

而 Range syntax 提供了更豐富的變化,比如 ~1.0.1 < 1.0.9,就會確保不會更新 Patch 超過 9,^1.0.1 < 1.3.0,就能確保 Minor 不會超過 3,諸如此類的應用讓開發者能準確的控制版本範圍

避免前綴

通常 npm config 的預設可能會是在每次 npm install 後,在 package.json 中的 version 前都加上 ~ or ^

對前綴有特定需求可以更改 npm config set prefix <prefix-symbol>,如果不想要任何前綴符號出現,則可以用 npm install --save-exact,就能避免前綴符號在做完安裝或更新後出現在 package.json

避免 package-lock 出現錯誤的更新

package-lock.json 算是 package.json 對應的細節

package.json 只是做單純的版本控制,比較像是版本索引,如果手動更改了 package.json 其中一個軟體的版本號碼,再做 npm install, 就會發現 package-lock.json 也會隨之更新

在背後真正管理軟體依賴關係的是 package-lock,裡面會有每個軟體的細項,比如他的來源的 url,還有 checksum 字串,以及軟體是不是又依賴於其他軟體的資訊(這滿重要的)

在開發的時候遇到在不同環境的遠端機器上執行 npm install 特定軟體時,npm 改變了該軟體在 package-lock.json 的來源,registry 跟應該要有的不一樣,原因是在那個環境下的 npm registry 可能有多組

所以要加上 --registry option,在該軟體的安裝上指定特定的 registry 來源

1
npm install --registry=<url> @<package-name>@<version>

或是設回預設的 url: http://registry.npmjs.org

後來發現在不同 platform 執行一樣的 install, npm 可能會在 package-lock.json 對其他的軟體做了非預期的修改,在網上找到有些開發者也有遇到這種問題

package-lock 相關的 issue

類似的困擾還沒有得到官方解決,目前比較可能(因為還沒遇到問題但不代表是正解)的解法是加上 --no-optional,避免安裝選擇性的依賴

1
npm install --no-optional @<package-name>@version

心得

此篇有點瑣碎,主要是一些在 npm 上遇到的眉眉角角,怕自己過了就忘記了,月底前來記錄一下

軟體版本號碼的控制,以前在學校也沒有學過,就算實習也沒什麼深入了解,剛出社會正職工作時也不太會碰到,都是處在有什麼 task 就做什麼,這次也算是一個機會,因為任務相關,稍微參與了版本號的 thread,才知道原來這些不同數字背後都是有意義的XD