柚子快報(bào)邀請(qǐng)碼778899分享:前端 npm依賴(lài)版本鎖定詳解
npm中有一個(gè)package-lock.json的文件,即npm依賴(lài)鎖文件,用來(lái)描述npm依賴(lài)生成的確切樹(shù),這樣不管你的依賴(lài)有何種更新,都會(huì)按照這個(gè)確切樹(shù)來(lái)安裝使用。
不同的包管理工具對(duì)應(yīng)不同的鎖文件: ● npm => package-lock.json ● yarn => yarn.lock ● pnpm => pnpm-lock.yaml
整體上大同小異,本文主要以npm為例。
一、semver 版本控制規(guī)范
在軟件管理的領(lǐng)域里存在著被稱(chēng)作“依賴(lài)地獄”的死亡之谷,系統(tǒng)規(guī)模越大,加入的包越多,你就越有可能在未來(lái)的某一天發(fā)現(xiàn)自己已深陷絕望之中。 為了解決依賴(lài)包的版本混亂問(wèn)題,制定了這個(gè) semver 規(guī)范。
版本格式:【主版本號(hào).次版本號(hào).修訂號(hào)】,版本號(hào)遞增規(guī)則如下:
主版本號(hào):當(dāng)你做了不兼容的 API 修改,(不兼容更新)次版本號(hào):當(dāng)你做了向下兼容的功能性新增,(功能新增)修訂號(hào):當(dāng)你做了向下兼容的問(wèn)題修正。(bug修復(fù)) 先行版本號(hào)及版本編譯信息可以加到“主版本號(hào).次版本號(hào).修訂號(hào)”的后面,作為延伸。(例如beta、test版本)
(更詳細(xì)內(nèi)容參考官網(wǎng)文檔:https://semver.org/lang/zh-CN/)
二、安裝依賴(lài)時(shí)的版本規(guī)則
npm依賴(lài)規(guī)則中,還有 >、>=、<、<=、x、*、-、||、~、^ 等符號(hào)。通過(guò)在版本號(hào)前面加上這些符號(hào),可以有效的限制依賴(lài)的版本。
version:必須依賴(lài)某個(gè)具體的版本。如:2.5.2,表示必須安裝2.5.2版本。>version:必須大于某個(gè)版本。>=version:大于或等于某個(gè)版本。 如果次版本號(hào)(Y)指定了,那么次版本號(hào)(Y)不變,而修訂號(hào)(Z)任意。如果次版本號(hào)(Y)和修訂號(hào)(Z)未指定,那么次版本號(hào)(Y)和修訂號(hào)(Z)任意。 ^version:向上兼容某個(gè)版本。 ○ 從版本號(hào)最左側(cè)開(kāi)始,到首個(gè)非零數(shù)字,這些位置固定,其余位置任意。如果缺少某個(gè)位置,則這個(gè)位置可以任意。 "~2.5.2" // 表示 >=2.5.2 且 <2.6.0 "~2.5" // 表示 >=2.5.0 且 <2.6.0 "~2" // 表示 >=2.0.0 且 <3.0.0 "^2.5.2" // 表示 >=2.5.2 且 <3.0.0 "^0.1.3" // 表示 >=0.1.3 且 <0.2.0 "^0.0" // 表示 >=0.0.0 且 <0.1.0 使用npm安裝依賴(lài)時(shí)在 package.json 里生成的默認(rèn)是 ^version 形式,安裝時(shí)會(huì)安裝最新的依賴(lài)。 這意味著,在多人協(xié)作時(shí),如果一個(gè)人安裝了某個(gè)版本,另一個(gè)人在安裝時(shí)這個(gè)依賴(lài)更新了此版本號(hào),就會(huì)安裝另一個(gè)版本,不同的版本會(huì)有差異,可能就會(huì)出現(xiàn)問(wèn)題。另外在本地構(gòu)建和服務(wù)器構(gòu)建時(shí)可能也會(huì)有類(lèi)似的差異導(dǎo)致問(wèn)題。 三、依賴(lài)鎖定 如果所有的node包都嚴(yán)格符合語(yǔ)義化版本(semver)管理的規(guī)則,那么npm的最優(yōu)版本號(hào)就能保證所下載的依賴(lài)包一定是與代碼兼容的。 由于無(wú)法保證這一前提,如果想要保證他人下載的依賴(lài)包與我們的代碼絕對(duì)兼容,就需要鎖定項(xiàng)目中依賴(lài)包的版本號(hào)。 1. 寫(xiě)死版本號(hào)鎖定 最簡(jiǎn)單的方法,就是指定具體版本號(hào),可以將package.json中版本號(hào)開(kāi)頭的 ^ 和 ~ 等標(biāo)記去掉。 后續(xù)安裝新的依賴(lài)包時(shí),則使用 npm i --save-exact 缺陷:無(wú)法鎖定次級(jí)依賴(lài)的版本號(hào),即依賴(lài)包的依賴(lài)包。 2. 鎖文件 由于在重新安裝依賴(lài)時(shí),依賴(lài)樹(shù)模塊的版本存在著不確定性,為了解決這個(gè)問(wèn)題,npm提供了 npm-shrinkwrap.json 或 package-lock.json 文件,這兩種文件被稱(chēng)為包鎖或鎖文件。 1)npm shrinkwrap 在npm 5版本以前(不包括npm 5),可以通過(guò)執(zhí)行 npm shrinkwrap 命令,創(chuàng)建一個(gè)新的或覆蓋已有的 npm-shrinkwrap.json 文件。該文件記錄了目前所有依賴(lài)包(及更底層依賴(lài)包)的版本信息。 當(dāng)再次運(yùn)行npm install命令重新安裝依賴(lài)時(shí),npm首先會(huì)找npm-shrinkwrap.json文件,依照其中的信息來(lái)準(zhǔn)確地安裝每一個(gè)依賴(lài)包,只有當(dāng)這個(gè)文件不存在時(shí),npm才會(huì)使用package.json。 每次更新package.json或者node_modules時(shí),如: npm install新包、npm update、npm uninstall等操作,為了保證所有開(kāi)發(fā)人員的資源一致,還是要手動(dòng)運(yùn)行npm shrinkwrap更新npm-shrinkwrap.json文件。npm shrinkwrap計(jì)算時(shí)是根據(jù)當(dāng)前依賴(lài)安裝的目錄結(jié)構(gòu)生成的,如果不能保證package.json文件定義的依賴(lài)與node_modules下已安裝的依賴(lài)是匹配、無(wú)冗余的,建議在執(zhí)行npm shrinkwrap命令前清理依賴(lài)并重新安裝(rm-rf node_modules&&npm install)或精簡(jiǎn)依賴(lài)(npm prune)。 2)package-lock.json 在npm 5以后,運(yùn)行npm intall會(huì)自動(dòng)生成一個(gè)新文件package-lock.json,其內(nèi)容跟上面提到的npm-shrinkwrap.json基本一樣,在修改pacakge.json或者node_modules時(shí)會(huì)自動(dòng)產(chǎn)生或更新它。 當(dāng)項(xiàng)目中已存在package-lock.json文件,再安裝項(xiàng)目依賴(lài)時(shí),將以該文件為主進(jìn)行解析安裝指定版本的依賴(lài)包,而不是使用package.json來(lái)解析和安裝。 因?yàn)閜ackage-lock.json為每個(gè)模塊及其每個(gè)依賴(lài)項(xiàng)都指定了版本、位置和完整性哈希,所以它每次創(chuàng)建的安裝都是相同的。 cnpm并不支持package-lock。 使用cnpm install時(shí),并不會(huì)生成package-lock.json文件。即使項(xiàng)目中已有package-lock.json文件,執(zhí)行cnpm install命令,cnpm 也不會(huì)識(shí)別,仍會(huì)根據(jù)package.json安裝依賴(lài)。因此,盡量避免直接使用cnpm install安裝項(xiàng)目的依賴(lài)。 3)區(qū)別和聯(lián)系 package-lock.json是npm 5的新特性,且不向下兼容,因此如果npm版本是5以下,還是使用npm shrinkwrap命令。package-lock.json和npm-shrinkwrap.json這兩個(gè)文件的優(yōu)先級(jí)都比package.json高。 同一個(gè)項(xiàng)目里,如果不存在這兩個(gè)文件,在運(yùn)行npm install或者初始化項(xiàng)目npm init時(shí),會(huì)自動(dòng)生成一個(gè)package-lock.json(npm 5及以上)。如果這兩個(gè)文件都存在,安裝依賴(lài)則是依據(jù)npm-shrinkwrap.json,而忽略package-lock.json。如果項(xiàng)目里不存在package-lock.json,運(yùn)行命令npm shrinkwrap后,會(huì)創(chuàng)建一個(gè)npm-shrinkwrap.json文件如果存在package-lock.json,則會(huì)將其重命名為npm-shrinkwrap.json。 npm-shrinkwrap.json只有在運(yùn)行npm shrinkwrap命令時(shí)才會(huì)創(chuàng)建或更新;而package-lock.json會(huì)在修改pacakge.json或者node_modules時(shí)自動(dòng)產(chǎn)生或更新。 四、要不要鎖 一直以來(lái)這都是個(gè)有爭(zhēng)議的問(wèn)題。 1. 兩種鎖的方式: 一是在package.json里對(duì)個(gè)別依賴(lài)寫(xiě)死版本號(hào)鎖定。二是通過(guò)鎖文件對(duì)所有依賴(lài)都鎖定。 2. 個(gè)人建議: 當(dāng)項(xiàng)目的維護(hù)可能陷入停滯或者很少更新時(shí),通過(guò)鎖文件來(lái)鎖住依賴(lài),保證項(xiàng)目即使過(guò)了很長(zhǎng)時(shí)間依然能穩(wěn)定跑起來(lái)。當(dāng)項(xiàng)目和依賴(lài)有專(zhuān)門(mén)的維護(hù)團(tuán)隊(duì)來(lái)長(zhǎng)期維護(hù)時(shí),不鎖依賴(lài),一般這種依賴(lài)的版本更新會(huì)比較規(guī)范,有問(wèn)題也能及時(shí)發(fā)現(xiàn)和修復(fù)。 ○ 如果是個(gè)別依賴(lài)的維護(hù)不穩(wěn)定,這部分依賴(lài)可以通過(guò)package.json寫(xiě)死版本號(hào)來(lái)鎖定。 其他情況就需要綜合考量了,利弊都有,沒(méi)有絕對(duì)的說(shuō)法。 柚子快報(bào)邀請(qǐng)碼778899分享:前端 npm依賴(lài)版本鎖定詳解 文章鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。