package-lock.json和yarn.lock是您最好的朋友

github-npm-blog-696x391.png

爲何要保留它們以及什麼時候要拋棄它們? css

你是否是遇到和思考過下面的問題?html

  • 什麼是package-lock.json(或yarn.lock)?
  • 咱們爲何須要它?
  • 個人package-lock.json文件中有衝突
  • 我提交時會忽略它
  • 我要把它刪掉

更糟糕的是,您可能已經刪除了它,並提交了您的 PR 或 push 到master!前端

若是是這種狀況,那麼您已經修改了比預期大得多的源代碼。node

您能夠控制本身的源代碼,但package-lock.json和yarn.lock文件可確保您的第三方代碼在兩次提交之間不會發生變化

將第三方包視爲一等公民

在解開包鎖文件的祕密時,理解這一點相當重要。許多開發人員只考慮更改本身的源代碼,可是經過軟件包管理器(如npm和yarn)安裝的第三方代碼也一樣重要,甚至更多。git

爲何?由於它們會致使很難追蹤的bug。程序員

換句話說,若是沒有package lock文件,您就不知道代碼中發生了什麼變化,從而產生了您可能觀察到的bug。您可能會盯着提交之間的代碼差別,花上幾個小時思考這些更改不可能致使這個問題。github

你是對的,這是你看不到的代碼致使問題。chrome

給予您的第三方軟件包應有的尊重,並將他們視爲您本身的代碼。typescript

將您的包看做是由多個開發人員提交給您的項目的二進制代碼,就好像它是開源的同樣

讓咱們解決以上幾點。express

什麼是 package lock 文件?水果和蔬菜的比喻

這樣想吧,你喜歡吃水果和蔬菜。每週您都須要購買水果和蔬菜,所以您有一個標準的購物清單,不多更改:

每週購物清單:

水果
蔬菜

如今,您實際上喜歡某些種類的水果和蔬菜,所以您想使列表更具體:

每週購物清單:

 水果
    蘋果
    葡萄
    番茄
蔬菜
    洋蔥
    土豆
    南瓜

你知道你的口味比這個好一點,因此你添加了一些關於每種水果和蔬菜的細節:

每週購物清單:

水果
    蘋果:紅色
    葡萄:綠色
    番茄:紅色
蔬菜
    洋蔥:白色,紅色或棕色
    土豆:洗乾淨的或刨皮了的
    南瓜:任何一種

好的,咱們有清單,並且至關詳細,可是咱們的一些水果和蔬菜還有一些變更的空間。因此咱們出去買了清單上的東西,最後獲得了一張收據:

收據 - 01/01/2020

蘋果 - 富士
番茄 - 紅色
葡萄 - 綠的
洋蔥 - 棕色
土豆 - 洗淨
南瓜 - 原產地

看到這裏發生了什麼嗎?儘管咱們沒有具體說明一些水果和蔬菜的確切類型,但咱們不得不購買確切的類型。

如今,當咱們回到家,吃了咱們的蘋果,煮了咱們全部的蔬菜,咱們對咱們的選擇很是滿意,因此咱們保留着收據,下次帶着它去購物,連同咱們的清單。

由於咱們有收據,上面列出了咱們上週購買的商品,因此本週咱們購買的商品徹底相同。

這可能會一直持續下去,可是假設咱們對蘋果的口味發生了變化,因此咱們寫了一個新的清單:

每週購物清單

水果:
    蘋果:綠的
    葡萄:白的
    番茄:紅色
蔬菜:
    洋蔥:白的紅的或者棕色的
    土豆:洗乾淨的或刨皮了的    
    南瓜:任何一種

如今,當咱們去購物時,咱們將不得不購買某種綠色蘋果。結算時,咱們獲得了以下的收據:

收據- 02/01/2020

蘋果 - 南方青蘋果
番茄 - 紅色
葡萄 - 綠的
洋蔥 - 棕色
土豆 - 洗淨
南瓜 - 原產地

咱們已經購買了與上週徹底相同的東西,除了咱們的蘋果換成了南方青蘋果!

由於咱們保留了收據,因此咱們可以記住咱們喜歡的全部水果和蔬菜,並繼續購買相同的水果和蔬菜。

可是,若是咱們扔掉收據怎麼辦?咱們必須從頭開始,並可能最終獲得咱們不喜歡的水果和蔬菜。

獲得它了購物清單、收據、水果和蔬菜,但這是一篇有關軟件工程的文章?

讓咱們從新回到軟件角度:

  1. 購物清單表明您的 package.json 文件
  2. 每一個水果和蔬菜表明一個package
  3. 水果或蔬菜的類型表明該package的確切版本或可接受版本的範圍
  4. 收據表明您的 package-lock.jsonyarn.lock 文件

當咱們保存收據,也就是咱們的 package lock(包鎖定) 文件時,咱們可以確保得到相同package的版本,直到咱們的購物清單,也就是咱們的 package.json 文件發生了變化。

若是咱們丟掉包鎖定文件,極可能最終獲得的包不是咱們指望的。

包鎖定文件使提交保持不變

若是在所選的版本控制工具中打開提交圖,則圖上的每一個尖點都表明一個版本的代碼,若是該代碼的版本被檢索(pull)是不可變的,則不管誰以及什麼時候檢索它都應該是相同的。

若是您的代碼庫包含具備依賴性的 package.json 文件,而不是package-lock.jsonyarn.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 用戶使用 npmyarn.lock,則容許這樣作的機制稱爲 package-lock.json 文件。

此文件的存在可確保針對給定的提交安裝相同的軟件包版本,所以不管誰使用它,什麼時候使用它,您本身的源代碼和第三方打包的代碼都是相同的。

刪除或不提交這些文件可能會致使應用程序發生不可預測的行爲,由於對於同一次提交,軟件包的實際安裝版本可能會隨着時間而變化,若是發現錯誤是由錯誤的程序包引發的,則可能很難追蹤到它們。

所以,建議您提交而不刪除這些文件,除非您打算根據 package.json 規範更新軟件包,而且準備進行完全的測試或快速修復生產中發現的全部錯誤。

感謝您的閱讀,我但願這能解釋 package-lock.jsonyarn-lock.json 文件。


相關連接:


聚焦大前端技術和程序員成長,若是對你有所啓發和幫助,能夠點個關注、收藏,也能夠留言討論,這是對做者的最大鼓勵。

做者簡介:Web前端工程師,全棧開發工程師、持續學習者。

相關文章
相關標籤/搜索