NodeJS的lock file及其使用

什么是lock file

lock file文件描述了整顆依賴樹,包含了特定版本的傳遞依賴(依賴嵌套)關(guān)系。npm中用的是package-lock.json,yarn中用的是yarn.lock。

package-lock.json如下所示:

1.png

yarn.lock如下所示:

2.png

lockfile包含的關(guān)鍵信息包括

  • 安裝每個依賴的實(shí)際版本
  • 每個依賴的依賴(即傳遞依賴)
  • 包的校驗和(以驗證包的完整性)

使用lockfile的方法如下:

npm ci # will install exactly what's in the package-lock.json
yarn install --frozen-lock-file # will install exactly what's in yarn.lock without updating it

什么時候使用lockfile

當(dāng)我們在構(gòu)建一個web應(yīng)用時,建議使用上述的命令,來執(zhí)行構(gòu)建和發(fā)布。包括在CI中使用上述命令。這樣我們可以確保每個開發(fā)驗證人員、構(gòu)建系統(tǒng)/CI系統(tǒng)使用完全相同的依賴項。

因此,在yarn和npm的文檔里都有建議,在提交代碼的時候,把lockfile也提交進(jìn)GIT倉作為代碼的一部分。

這也有利于可重復(fù)構(gòu)建。對外交付時,任何時候都可以通過相同的代碼構(gòu)建出一致的包,客戶也易于理解與驗收。

什么時候不使用lockfile

當(dāng)我們代碼的構(gòu)建結(jié)果是一個中間依賴,即被其他項目依賴時,不建議使用。換言之,lockfile應(yīng)該進(jìn)入頂層項目(最終用戶消費(fèi)的程序)的源碼版本控制。

為什么被依賴件的源碼倉不建議使用lock file呢?

主要原因在于npm倉庫上發(fā)布的包本身。即,你發(fā)布到npm的內(nèi)容并不總是與git倉上的內(nèi)容相同。

npm使用npm pack命令將需要發(fā)布的文件打成一個tarball,你可以嘗試使用如下命令來查看npm打包了哪些文件

npm pack --dry-run

也可以在 npm的doc 查看打包的完整文件列表,摘錄其打包的內(nèi)容如下

Certain files are always included, regardless of settings:

  • package.json
  • README
  • CHANGES / CHANGELOG / HISTORY
  • LICENSE / LICENCE
  • NOTICE
  • The file in the "main" field

README, CHANGES, LICENSE & NOTICE can have any case and extension.

Conversely, some files are always ignored:

  • .git
  • CVS
  • .svn
  • .hg
  • .lock-wscript
  • .wafpickle-N
  • .*.swp
  • .DS_Store
  • ._*
  • npm-debug.log
  • .npmrc
  • node_modules
  • config.gypi
  • *.orig

可以看到,npm只打包了package.json,而沒有打包package-lock.json。

這種情況下,當(dāng)別人的工程依賴你的npm包的時候,無法下載到你的工程的package-lock.json,導(dǎo)致實(shí)際依賴的你的包的傳遞依賴(即你所依賴的包)的版本不一定與你發(fā)布時的一致。

所以,作為一個被別人依賴的模塊,關(guān)鍵在于讓自己“靠譜”一些,而這點(diǎn)并不依靠lock文件。建議的“靠譜”方法包括:

  1. 嚴(yán)格遵循 semver 語義化版本的原則來進(jìn)行版本發(fā)布。對不遵循 semver 發(fā)布的模塊敬而遠(yuǎn)之。
  1. 選擇依賴時,盡量選擇npm 上有較大的下載量的,當(dāng)遇到模塊問題時,波及范圍越廣,其修復(fù)的速度越快。
  1. 開源模塊在github 上的問題反饋迅速,或者是由一些知名開發(fā)者維護(hù)。質(zhì)量有一定的保障
  1. 版本號中,patch 位變更的發(fā)布不多(說明 bug fix 不多)。

有的人會認(rèn)為,即使如此,仍然應(yīng)該把package-lock文件歸檔到git倉,哪怕它實(shí)際沒有被使用。畢竟要使用lockfile都是單獨(dú)的命令,如果不使用的話,歸檔也沒什么影響。但是,事實(shí)真的如此嗎?

首先,npm包管理是使用的semver 語義化版本的機(jī)制來幫助開發(fā)者管理依賴,開發(fā)者可以在 package.json中通過 ^1.1.0 或者 ~1.0.0 的方式來引入模塊,如果開發(fā)者信任他們依賴的模塊,開發(fā)者可以通過 ^ 來鎖定一個模塊的大版本,這樣在每次重新安裝依賴或者打包的時候,都能夠享受到這個包所有的新增功能和 bug 修復(fù)。而這個模塊如果遵循 semver 原則,也不用擔(dān)心它會引入一些不兼容變更導(dǎo)致項目出現(xiàn)一些未知異常。最終開發(fā)者需要關(guān)心的其實(shí)只有直接依賴的這些模塊是否足夠靠譜。 這樣一來,每個模塊對自身的依賴負(fù)責(zé),一個項目雖然只直接依賴了十來個模塊,但其最終卻間接的依賴了上千個模塊。真正想要通過package-lock.json去管理好這一份多達(dá)上千個模塊的模塊是非常困難的。(一個關(guān)于lockfile成為安全侵入的入口的例子見這里https://snyk.io/blog/why-npm-lockfiles-can-be-a-security-blindspot-for-injecting-malicious-modules/,例子中,正是由于lockfile動輒幾百上千行的修改,對commit審核造成了很大的壓力,而通常一個commit也就幾十行的修改。)

其次,在有l(wèi)ockfile文件的情況下,npm install的真正行為情況如下:

1、npm 5.0.x 版本,不管package.json怎么變,npm install 時都會根據(jù)lock文件下載

2、5.1.0 - 5.4.2版本 npm install 會無視lock文件,去下載符合規(guī)則的最新的包。

3、5.4.2版本后,如果改了package.json,且package.json和lock文件不同,那么執(zhí)行npm install時npm會根據(jù)package.json中的版本號去下載最新的包,并更新lock文件。如果沒有更新package.json,那么npm install會根據(jù)lock文件下載,而不會理會package.json中實(shí)際的包的版本是否有更新。

換句話說,當(dāng)存在lockfile的情況下,即使有新的補(bǔ)丁包存在,都可能不會被使用 。而這點(diǎn)顯然不是我們希望的

最后,重申一遍,lockfile應(yīng)該進(jìn)入頂層項目(最終用戶消費(fèi)的程序)的源碼版本控制,中間模塊不建議使用lockfile。

P.S:有人會認(rèn)為開源社區(qū)大多用了lock。其實(shí)仔細(xì)看github上的提交就會發(fā)現(xiàn),lock文件很多是不允許個人提交的,lock文件的更新大多由機(jī)器人自動更新,也就是說,這里的lock文件,是作為一個CI快照更新上庫的。同樣的,也有不少高星的開源社區(qū),例如ESlint,庫上沒有l(wèi)ock文件。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容