我們為什麽需要 lock 文件
前言
從 Yarn 橫空出世推出 lock 文件以來,已經兩年多時間了,npm 也在 5.0 版本加入了類似的功能,lock 文件越來越被開發者們接收和認可。本篇文章想從前端視角探討一下我們為什麽需要 lock 文件,以及它的一些成本與風險,當然其中一些觀點對於後端也是適用的。
為什麽需要 lock 文件
之所以需要 lock 文件,我覺得主要有 4 個原因:
確保各環境依賴版本的一致性
軟件開發一般有著好幾個環境,通常包括本地開發環境、集成測試環境、預發布環境以及線上環境。各環境依賴版本不一致通常是 bug 的一大來源,大家可能碰到過“在我的電腦上是好的”這種問題,也許就是依賴版本不一致導致的。這種問題通常很難定位,因為你很難確定到底是自己的問題還是依賴的問題。這也是 Yarn 推出 lock 文件的初衷之一,使用了 lock 文件,你在排查問題時至少可以排除依賴版本不一致這個因素。
語義化版本並不絕對可靠
一些開發者不願意使用 lock 文件,一個主要原因是他們希望基於語義化版本號讓依賴自動升級,認為只要選擇的依賴可靠,大版本不變化就可以放心升級。在絕大多數情況下這麽做不會有問題,但是也有意外情況,比如:
React 在 v16.4.0 對 getDerivedStateFromProps 的調用時機進行了調整。React 在 v16.3.0 引入了這個 API,最初只有在父組件引起的重渲染過程中會被調用,v16.4.0 調整為在所有渲染過程中都會被調用。如果你在不知情的情況下(自動)把 React 從 v16.3.0 升級到了 v16.4.0,那麽極端情況下你的應用就會出問題。
雖然只有在很極端的情況下你才會碰到類似問題,但是這種問題本來就是不怕一萬就怕萬一。
可控的升級依賴
現在通過 webpack 把依賴單獨提取為一個 vendor.js 是個很常見的做法,因為依賴變更相對來說沒那麽頻繁,再配合上強緩存,可以做到即使發布了新版本,用戶也可以使用緩存的 vendor.js 而不必重新下載。通常我們的應用不止一個依賴,這些依賴肯定也不是同一時間發布更新,如果不使用 lock 文件讓其自由更新,可能會導致 vendor.js 緩存失效多次(每個依賴更新都會導致緩存失效)。如果使用 lock 文件就可以積累一段時間,讓多個依賴集中更新,甚至跳過一些小版本更新,從而提高 vendor.js 的緩存命中率。
安全問題
幾個月前 ESLint 發生了一個安全事故,一個攻擊者竊取了 ESLint 維護者的 npm 賬戶,並發布了惡意版本的 eslint-scope 和 eslint-config-eslint(都是更新的小版本),其中前者是 babel-eslint 和 webpack 的依賴。如果沒有使用 lock 文件,那麽你就極有可能中招,ESLint 事後也建議開發者使用 lock 文件來避免自動安裝新版本。
成本
使用 lock 文件自然會增加一點項目的維護成本,因為依賴不會再自動升級,所以需要項目維護者每隔一段時間手動進行升級。另外如果兩個人同時修改了依賴,解決 lock 文件的沖突也是一件很麻煩的事。
但是手動升級依賴也有一些額外的好處,至少你升級每個依賴時都要去看一下它的 change log,這樣可以對每一次升級做到心中有數,這也有助於你掌握依賴的發展趨勢。比如前文提到的 React 的例子,只要你在升級時看一眼它的 change log,就很容易避開可能出現的問題。
風險
我唯一能想到的風險就是依賴版本固化問題,如果你使用了 lock 文件又沒有花時間跟精力去維護它,那麽你的項目就很容易陷入依賴版本固化的問題。如果太久沒有升級依賴,你當前使用的版本跟最新版差別太大,升級就會很困難,考慮到現實成本問題,可能就永遠不會升級了。
但是如果不使用 lock 文件就能完全避免這個問題嗎,我想也不一定。不使用 lock 文件最多也只能在同一個大版本範圍內自動升級,如果依賴升級了大版本,你沒有花時間去升級,也會碰到同樣的問題。只是相對於不使用 lock 文件,問題暴露的晚一些而已。
原文地址:https://segmentfault.com/a/1190000016914977
我們為什麽需要 lock 文件