你是不是遇到和思考過下面的問題?
- 什么是package-lock.json(或yarn.lock)?
- 我們為什么需要它?
- 我的package-lock.json文件中有沖突
- 我提交時會忽略它
- 我要把它刪掉
更糟糕的是,您可能已經刪除了它,並提交了您的 PR 或 push 到master!
如果是這種情況,那么您已經修改了比預期大得多的源代碼。
您可以控制自己的源代碼,但package-lock.json和yarn.lock文件可確保您的第三方代碼在兩次提交之間不會發生變化
將第三方包視為一等公民
在解開包鎖文件的秘密時,理解這一點至關重要。許多開發人員只考慮更改自己的源代碼,但是通過軟件包管理器(如npm和yarn)安裝的第三方代碼也同樣重要,甚至更多。
為什么?因為它們會導致很難追蹤的bug。
換句話說,如果沒有package lock文件,您就不知道代碼中發生了什么變化,從而產生了您可能觀察到的bug。您可能會盯着提交之間的代碼差異,花上幾個小時思考這些更改不可能導致這個問題。
你是對的,這是你看不到的代碼導致問題。
給予您的第三方軟件包應有的尊重,並將他們視為您自己的代碼。
將您的包看作是由多個開發人員提交給您的項目的二進制代碼,就好像它是開源的一樣
讓我們解決以上幾點。
什么是 package lock 文件?水果和蔬菜的比喻
這樣想吧,你喜歡吃水果和蔬菜。每周您都需要購買水果和蔬菜,因此您有一個標准的購物清單,很少更改:
每周購物清單:
水果
蔬菜
現在,您實際上喜歡某些種類的水果和蔬菜,因此您想使列表更具體:
每周購物清單:
水果
蘋果
葡萄
番茄
蔬菜
洋蔥
土豆
南瓜
你知道你的口味比這個好一點,所以你添加了一些關於每種水果和蔬菜的細節:
每周購物清單:
水果
蘋果:紅色
葡萄:綠色
番茄:紅色
蔬菜
洋蔥:白色,紅色或棕色
土豆:洗干凈的或刨皮了的
南瓜:任何一種
好的,我們有清單,而且相當詳細,但是我們的一些水果和蔬菜還有一些變動的空間。所以我們出去買了清單上的東西,最后得到了一張收據:
收據 - 01/01/2020
蘋果 - 富士
番茄 - 紅色
葡萄 - 綠的
洋蔥 - 棕色
土豆 - 洗凈
南瓜 - 原產地
看到這里發生了什么嗎?盡管我們沒有具體說明一些水果和蔬菜的確切類型,但我們不得不購買確切的類型。
現在,當我們回到家,吃了我們的蘋果,煮了我們所有的蔬菜,我們對我們的選擇非常滿意,所以我們保留着收據,下次帶着它去購物,連同我們的清單。
因為我們有收據,上面列出了我們上周購買的商品,所以本周我們購買的商品完全相同。
這可能會一直持續下去,但是假設我們對蘋果的口味發生了變化,所以我們寫了一個新的清單:
每周購物清單
水果:
蘋果:綠的
葡萄:白的
番茄:紅色
蔬菜:
洋蔥:白的紅的或者棕色的
土豆:洗干凈的或刨皮了的
南瓜:任何一種
現在,當我們去購物時,我們將不得不購買某種綠色蘋果。結算時,我們得到了如下的收據:
收據- 02/01/2020
蘋果 - 南方青蘋果
番茄 - 紅色
葡萄 - 綠的
洋蔥 - 棕色
土豆 - 洗凈
南瓜 - 原產地
我們已經購買了與上周完全相同的東西,除了我們的蘋果換成了南方青蘋果!
因為我們保留了收據,所以我們能夠記住我們喜歡的所有水果和蔬菜,並繼續購買相同的水果和蔬菜。
但是,如果我們扔掉收據怎么辦?我們必須從頭開始,並可能最終得到我們不喜歡的水果和蔬菜。
得到它了購物清單、收據、水果和蔬菜,但這是一篇有關軟件工程的文章?
讓我們重新回到軟件角度:
- 購物清單代表您的
package.json
文件 - 每個水果和蔬菜代表一個package
- 水果或蔬菜的類型代表該package的確切版本或可接受版本的范圍
- 收據代表您的
package-lock.json
或yarn.lock
文件
當我們保存收據,也就是我們的 package lock(包鎖定) 文件時,我們能夠確保獲得相同package的版本,直到我們的購物清單,也就是我們的 package.json
文件發生了變化。
如果我們丟掉包鎖定文件,很可能最終得到的包不是我們期望的。
包鎖定文件使提交保持不變
如果在所選的版本控制工具中打開提交圖,則圖上的每個尖點都代表一個版本的代碼,如果該代碼的版本被檢索(pull)是不可變的,則無論誰以及何時檢索它都應該是相同的。
如果您的代碼庫包含具有依賴性的 package.json
文件,而不是package-lock.json
或 yarn.lock
文件(或其他軟件包管理器用來鎖定軟件包版本的另一個文件),則不是這種情況。如果在不同的時間訪問提交,我們可以得到不同版本的軟件包。
這是因為包的新版本一直都在發布,而且我們已經允許在一些我們將接受的版本中存在差異。例如:
{
"name": "my-angular-app",
"version": "1.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^8.2.1",
"@angular/common": "^8.2.1",
"@angular/compiler": "^8.2.1",
"@angular/core": "^8.2.1",
"@angular/forms": "^8.2.1",
"@angular/http": "^8.0.0-beta.10",
"@angular/platform-browser": "^8.2.1",
"@angular/platform-browser-dynamic": "^8.2.1",
"@angular/router": "^8.2.1",
"core-js": "^2.5.4",
"csstype": "^2.5.8",
"ng2-file-upload": "^1.3.0",
"rxjs": "~6.5.3",
"zone.js": "~0.9.1",
"typescript": "~3.5.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.803.19",
"@angular/cli": "^8.3.19",
"@angular/compiler-cli": "^8.2.1",
"@angular/language-service": "^8.2.1",
"@nguniversal/express-engine": "^7.0.2",
"@types/jasmine": "~2.8.8",
"@types/jasminewd2": "~2.0.3",
"@types/node": "~8.9.4",
"codelyzer": "~4.5.0",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~3.0.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~1.1.2",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.4.0",
"ts-node": "~7.0.0",
"tslint": "~5.11.0"
}
}
注意所有的 〜
和 ^
嗎?如果在不同的時間安裝這些軟件包,則可能會導致下載這些軟件包的不同版本。
盡管package.json文件中存在差異,但保留package-lock.json或yarn.lock文件將鎖定這些版本。
我將讓一些數字來說話,yarn
初始安裝后,node_modules
文件夾中文件的大小和數量
刪除 node_modules
並重新安裝后的文件大小和數量,保持yarn.lock
刪除 node_modules
並重新安裝,刪除 yarn.lock
之后的文件大小和數量
上述明細表面,在刪除 node_modules
並重新安裝包之后,node_modules
文件夾沒有發生任何變化。
但是,在刪除了 node_modules
文件夾和 yarn.lock
文件之后,又有了1507個文件,它們的大小總計超過7mb。
這些多余的文件到底是什么,其中一些會進入我們應用程序的運行代碼中嗎?可怕的是我們可能永遠不會知道。
刪除或不提交您的package-lock.json 或 yarn.lock 就像說"提交我的代碼並隨機修改我們源代碼其余部分的 X%"
刪除程序包鎖定是否安全?
您是否曾經在代碼庫上做過跨越大量不相關的功能的重大重構?也許你有意更新了主要庫,例如前端框架,你不確定什么,如果有什么可能會壞掉,所以你在你的應用程序上運行了一個完整的回歸測試?
好吧,如果您要刪除軟件包鎖定文件,我可能會建議您執行相同的步驟。
如果更改代碼的一個大的橫截面會導致您運行一個完整的回歸測試,那么也應該更改您的第三方代碼的一個大的比例
如果您確實想根據 package.json
文件獲取最新最好的軟件包(所有〜
和 ^
都可以更新為最新的補丁程序和次要版本),則可以刪除軟件包鎖定文件。
刪除程序包鎖定文件可能是利用package.json文件的強大功能的一種好方法,但請准備運行完整的回歸測試或解決任何意外行為
總結
除了在某些極端情況下,npm包不會被刪除,任何給定的版本也不會被修改,他們是不可變的。
對於任何給定的提交,您自己的代碼也應該是不可變的,如果對於 Yarn 用戶使用 npm
或 yarn.lock
,則允許這樣做的機制稱為 package-lock.json
文件。
此文件的存在可確保針對給定的提交安裝相同的軟件包版本,因此無論誰使用它,何時使用它,您自己的源代碼和第三方打包的代碼都是相同的。
刪除或不提交這些文件可能會導致應用程序發生不可預測的行為,因為對於同一次提交,軟件包的實際安裝版本可能會隨着時間而變化,如果發現錯誤是由錯誤的程序包引起的,則可能很難追蹤到它們。
因此,建議您提交而不刪除這些文件,除非您打算根據 package.json
規范更新軟件包,並且准備進行徹底的測試或快速修復生產中發現的所有錯誤。
感謝您的閱讀,我希望這能解釋 package-lock.json
和 yarn-lock.json
文件。