前言
上次講到用package-lock鎖版本來保證項目的一致性和穩定性。但在使用過程中,發現同一項目的不同開發,在install安裝依賴之後,package-lock.json文件會出現衝突,下面將針對這些問題進行探究和解決。
一、合分支時由於版本不同造成的衝突
簡而言之,就是兩個開發人員安裝了不同版本的新npm包,lock文件不同,從而導致的衝突。這類都屬於應有的衝突,只要由merge人員覈對版本號,選擇正確的版本,統一項目的lock版本即可。
二、package-lock中的resolve字段被不同環境的npm registry改寫,從而導致的很多衝突
這也是此次要探究的重點。明明版本號都是相同的,但是對應資源的下載地址不同,合分支時出現了很多的衝突。
1、resoled含義
從官網npm配置可知,resolved字段表示相對於倉庫源registry的一個包下載地址。如果這個包的下載地址和倉庫源不在同一服務上,那麼這個地址會是一個絕對路徑。
(在項目中,發現有的包,如【npx】包下面的依賴項的resolved值爲false,安裝發現,直接安裝npx此包,就包含了所有的下級依賴項(因此會比一般的tgz文件大,有5M,一般只會有7K。),所以可能下級依賴項的resolved值爲false,不會再根據下級依賴包再去安裝。)
2、出現衝突的原因及解決方式
(1)本地registry的配置不同,如有的是淘寶鏡像,有的是公司的等等。
本地registry的配置不同,會導致install時package-lock.json被改寫,造成衝突。所以爲了規避這個問題,需要在團隊內統一npm registry,可以在項目根目錄中使用.npmrc配置文件來配置項目級別的registry來進行統一。
如在his中的.npmrc
registry=http://npm.guahao-inc.com
(2)環境及npm和node版本不同
據反饋,在不同電腦上,由於npm和node,操作系統的不同,即便在項目裏設置了統一的.npmrc配置,在項目中執行npm install之後,package-lock.json文件會有些不同:
發現某些子依賴項的resoled:false,可能會換成“”空字符串,甚至換成url地址,造成衝突,還有就是可能增加optional字段,前者如上文所述,false替換爲“”不會造成問題,因爲都是不會再去重新下載子依賴。
(
示例:log-update這個包,是一個父依賴包和子依賴包都有resoled地址的,下載發現,父依賴包鏈接只會下載父依賴,他的所有子依賴會根據對應的resoled字段再去下載;而npx這個包,子依賴resolve的字段爲false或“”,根據父依賴地址安裝會發現其實已經安裝了所有的子依賴,所以resoleced字段爲false。
)
由於缺少官方說明,爲了重現和避免此類問題,我做了如下調研比對
對比node和npm版本
統計了團隊內大家的node和npm版本情況,覈查對應情況,在不刪除lock文件前提下,不同條件下分別執行install,結果如下
電腦 | npm版本 | node 版本 | npx包子依賴的resolved值 |
---|---|---|---|
mac | 6.4.1 | 10.12.0 | false |
mac | 6.4.1 | 10.15.3 | false |
mac | 6.4.1 | 10.16.0 | false |
mac | 6.13.4 | 10.15.3 | false |
mac | 6.14.4 | 10.15.3 | false |
mac | 6.7.0 | 11.13.0 | false |
windows | 6.13.4 | 10.15.3 | ""和url並存 |
windows | 6.7.0 | 11.14.0 | ""和url並存 |
windows | 6.13.4 | 11.14.0 | ""和url並存 |
初步結論
通過比對不同系統和npm及node版本在install npx這個包的情況:
1、mac下常用的node和npx版本在install之後,lock文件無差別,子依賴resolved字段內容爲false
2、windows下常用的node和npx版本在install之後,lock文件無差別,子依賴resolved字段內容爲“”或url地址。
可以初步得出,package-lock文件中存在的resolved的字段不一致,在同一系統和同一編輯器內不會出現,與常用的npm及node版本無關,可能是windows和mac系統下不同編輯器對resolved字段解析爲“”或false的方式不同。
另:
刪掉lock文件,後續的npx包install安裝時,子依賴沒有了resoleved字段(即爲“”,爲false,都是沒有這個字段,而是bundled: “true” . (表示在父依賴中已綁定安裝此子依賴),mac和windows統一。
三、解決方案
1、使用工具自動合併lock文件衝突
對於兩個不同install生成的lock文件,合併分支時發生衝突,npm官方做出了一定解釋並提供了一個專門用於自動合併lock文件衝突的工具:npm-merge-driver,這個工具設置的算法會合並兩個分支的所有依賴樹,綜合成一個新的lock文件。
此方法親測可行有效,在install時對於lock文件的衝突,會自動合併,能幫助開發者一鍵解決lock文件的衝突。
! 但此方式並沒有徹底解決mac和Windows(也可能是編輯器差異)導致的resolved:“”和false不同的問題。lock文件統一後,在mac中install,原本統一的resolved:""依舊會更新爲false。(不過“”和false起到的是一樣的作用,不影響代碼)
2、統一大版本node及npm,刪除原有resolved:false或“”的依賴包,重新install。
追本溯源,出現resolved:"false"和resolved: ''差異的依賴包,其實是子依賴已經bundled進父依賴的依賴包,從而子依賴的下載源爲false或“”,因而針對bundled的npm依賴包,如npx,可以刪除古早的這個npx依賴包,重新install。這樣,package-lock文件會重新更新,原有的resoleved字段不再展示,而是展示一個“bundled: “true”的字段”。
此方式更新過lock文件後在mac和windows下重新install都不會再出現衝突。由官網有關resoleved和bundled所述:對於bundled的依賴,不會再包含resolved字段和integrity字段,這可以完全解決當下的衝突問題。
考慮到npm和node版本不同,還有可能導致增加optional字段(true可選,false不可選),因而最好統一node和npm的大版本
總結
對於resoled的衝突,解決方式如下
- 統一配置項目.npmrc中的registry地址
- 對於bundled的依賴,如npx,最好重新安裝,避免resolved字段差異(推薦)
- 對於lock文件衝突,如一時難以手動確認合併方式,推薦使用npm-merge-driver
- 建議統一node及npm大版本,目前已測可行爲:node >10.15.3 npm >6.13.4