[译] 理解 NPM 5 中的 lock 文件
- 原文地址:Understanding lock files in NPM 5
- 原文作者:Ji?í Pospí?il
- 譯文出自:掘金翻譯計劃
- 譯者:Changkun Ou
- 校對者:JackGit,?Aladdin-ADD
理解 NPM 5 中的 lock 文件
NPM 的下個主版本(NPM 5)在速度、安全性和一堆其他時髦的東西上,相比較前一個版本帶來了一些改進。然而從用戶的角度來看,最突出的就是全新的 lock 文件,不止一個?lock 文件。我們一會兒再談論這個。對于新手來說,一個?package.json?文件使用了語義化版本規范,去描述對于其他包的直接依賴,而這些包可能依賴于其他包等等,以此類推。lock 文件則是整個依賴關系樹的快照,包含了所有包及其解析的版本。
與之前版本相反,lock 文件現在包含一個 integrity 字段,它使用?Subresource Integrity?來驗證已安裝的軟件包是否被改動過,換句話來說,驗證包是否已失效。它依舊支持舊版本 NPM 中對包的加密算法 SHA-1,但是以后將默認使用 SHA-512 進行加密。
這個文件目前取消了?from?字段。眾所周知,這個字段和時常發生不一致的?version?字段一起,給代碼審查看文件改動差異時,帶來了不少痛苦。不過現在應該變得更加整潔了。
該文件現在增加了?lockfileVersion?字段來指定的 lock 格式的版本,并將其設置為1。這是為了使將來的格式更新時,不用去猜測該文件使用什么特定版本。以前的 lock 格式仍然支持并被識別為版本?0。
{"name": "package-name","version": "1.0.0","lockfileVersion": 1,"dependencies": {"cacache": {"version": "9.2.6","resolved": "https://registry.npmjs.org/cacache/-/cacache-9.2.6.tgz","integrity": "sha512-YK0Z5Np5t755edPL6gfdCeGxtU0rcW/DBhYhYVDckT+7AFkCCtedf2zru5NRbBLFk6e7Agi/RaqTOAfiaipUfg=="},"duplexify": {"version": "3.5.0","resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz","integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=","dependencies": {"end-of-stream": {"version": "1.0.0","resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz","integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4="},你可能已經注意到了,指向特定 URI 的文件的?resolved?字段仍然得到了保留。注意,NPM 現在可以(根據 .npmrc 中的設置)解析機器配置使用的不同倉庫,這樣的話,與 integrity 字段一起配合,只要簽名是匹配的,包的來源并無關緊要。
值得一提的是,lock 文件精確描述了?node_modules?目錄中所列出的目錄的物理樹。其優點是,即使不同的開發人員使用不同版本的 NPM,他們仍然不僅能夠得到相同版本的依賴,還可以使用完全相同的目錄樹。 這與其他包管理器(如?Yarn?)不同。 Yarn 僅以?flatten 格式?描述各個包之間的依賴關系,并依賴于其當前實現來創建目錄結構。這意味著如果其內部算法發生變化,結構也會發生變化。如果你想了解更多關于 Yarn 和 NPM 5 之間 lock 文件的區別,請查看?Yarn determinism。
雙 lock 文件
上面已經提到過 lock 文件不止一個。當安裝新的依賴關系或文件不存在時,NPM 將自動生成一個名為?package-lock.json?的 lock 文件。如開始所述,lock 文件是當前依賴關系樹的快照,允許不同機器間的重復構建。因此,建議將它添加到您的版本控制中去。
你可能會認為,使用?npm shrinkwrap?及其?npm-shrinkwrap.json?可以實現同樣的效果。你的想法沒錯,但創建新 lock 文件的原因是,這樣能夠更好的傳達一個信息,就是 NPM 真正支持了 locking 機制,這在以前確實是一個顯著的問題。
不過還是有一些區別。首先,NPM 強制該?package-lock.json?不會被發布。 即使你將其顯式添加到軟件包的?files?屬性中,它也不會是已發布軟件包的一部分。這種情況同樣不適用于npm-shrinkwrap.json?文件,哪怕這個文件可以是發布包的一部分、即便存在嵌套的依賴關系,NPM 也會遵守它。你可以簡單的通過運行?npm pack?來查看生成的歸檔內部的內容。
接下來,您可能會想知道在已經包含?package-lock.json?的目錄中運行?npm shrinkwrap?時會發生什么。答案很簡單,NPM 僅僅會把?package-lock.json?重命名為?npm-shrinkwrap.json。因為文件的格式是完全一樣的。
最好奇的還會問,當兩個文件都存在時會發生什么。 在這種情況下,NPM將完全忽略package-lock.json,只使用?npm-shrinkwrap.json。 當只使用 NPM 操縱文件時,這種情況不應該發生。
總結:
-
NPM 會在安裝包時自動創建?package-lock.json,除非已經有?npm-shrinkwrap.json,并在必要時更新它。
-
新的?package-lock.json?永遠不會被發布,而且應該將其添加到你的版本控制系統中去。
-
運行已經帶有?package-lock.json?文件的?npm shrinkwrap?命令將只會對其重命名為?npm-shrinkwrap.json。
-
當兩個文件處于某些原因同時存在時,package-lock.json?將被忽略。
這很酷,但是什么時候使用新的 lock 文件而不是舊的 shrinkwrap? 它通常取決于您正在處理的包的類型。
當開發庫時
如果你正在開發一個庫(如其他人所依賴的軟件包),則應使用新的 lock 文件。 另一種替代方案是使用 shrinkwrap,并確保它不會隨包發布(新的 lock 文件不會自動發布)。 但為什么不發布 shrinkwrap 呢? 這是因為 NPM 遵守在包中找到的 shrinkwraps,并且由于 shrinkwrap 總是指向單個包的特定版本,所以你無法利用 NPM 可以使用相同的包來滿足多個包的要求(在?semver?允許范圍內)的優勢。 換句話說,通過不去強制 NPM 來安裝特定的版本,您可以讓 NPM 更好的復用包,并使結果更小更快地組合。
這里有一個警告。當你正在開發庫時,因為倉庫中存在?package-lock.json?或?npm-shrinkwrap.json,所以每次都會獲得完全相同的依賴關系,這對于你的持續集成服務器也是如此。現在想象你的?package.json?指定某個包的依賴關系為?^1.0.0,也恰好是 lock 文件中指定的版本,并且每次安裝。到目前為止一切正常。但如果依賴項發布了一個新版本,并且意外的破壞了 semver 和你開發的包,這時候會發生什么?
遺憾的是,在出現錯誤報告之前,你可能無法注意到這個問題。在沒有 lock 文件的倉庫中,你的構建至少在 CI 服務器上會失敗,因為它總是嘗試去安裝依賴的?latest?版本,從而運行出錯的版本(只要該版本定期運行,而不僅僅是針對 PR)。 然而,當 lock 文件出現后,它將始終安裝能正常工作的被 lock 的版本。
然而,對于這個問題有幾個其他的解決方案。 首先,你可以犧牲問題重現的精確性,而不將 lock 文件添加到版本控制系統中。 其次,你可以做一個分離的配置來進行構建,在運行測試之前運行?npm update。 第三,你可以簡單的在你運行測試之前刪除 lock。 如何處理發現的損壞依賴是另一個話題了,其主要原因是因為 NPM 實現的 semver 不僅沒有涉及如此廣范圍的問題,而且還不支持特定版本的黑名單特性。
這當然就會引起一個問題,在開發庫的時候,是否真的值得將 lock 文件添加到版本控制中去。要記住的是,lock 文件不僅包含依賴關系,還包含?dev?的依賴關系。在這種意義下來講,開發庫與開發應用時類似(見下一節),無論什么時候都有著完全相同的 dev 依賴關系,并且不同設備也算一種優勢。
當開發應用時
好,那么最終用戶在終端中使用的包或打包的可執行文件會是個什么情況?在這種情況下,包就是最終結果,即應用。你想要確保最終用戶總能獲得你發布時所具有的確切依賴性。確保在安裝時讓 NPM 遵守規則,這就是您想要使用 shrinkwrap 的地方。 記住,使用?npm pack發布包時,你可以隨時查看軟件包的情況。
注意,在?package.json?中指定一個特定版本依賴是不夠的,因為你希望確保最終用戶獲得完全相同的依賴關系樹,包括其所有子依賴關系。而?package.json?中的一個特定版本保證只會發生在頂層。
其他類型的應用怎么樣,比如在倉庫內啟動的項目?這種情況并不重要。重要的是安裝正確的依賴項,而兩個 lock 都滿足這一點要求。隨你怎么選。
結束
沒了,就這么多。如果有哪里不對或者有一些一般性的意見,請隨時在 Twitter 上聯系我。如果你發現拼寫錯誤或語法問題,則可以在 GitHub 上找到這個文章。感謝你的幫助!
原文發布時間為:2017年6月16日
本文來自云棲社區合作伙伴掘金,了解相關信息可以關注掘金網站。
總結
以上是生活随笔為你收集整理的[译] 理解 NPM 5 中的 lock 文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1. 写出一个能创建多级目录的 PHP
- 下一篇: echo -e 参数