在JavaScript項目中鎖定npm依賴包版本


Node.js的依賴管理系統公認是非常先進的。這一篇文章來簡單談談npm如何管理項目的依賴包的版本。

下文大多翻譯自Express in Action一書第12章的相關內容

語義化版本號

npm默認所有的Node包都使用語義化版本號,英文叫做semantic versioning。這是一套指導開發人員如何增長版本號的規則,要求:

  • 每個版本號都形如1.2.3,由三個部分組成,依次叫做“主版本號”、“次版本號”和“修訂號”
  • 當新版本無法兼容基於前一版本的代碼時,則提高主版本號
  • 當新版本新增了功能與特性,但仍兼容前一版本的代碼時,則提高次版本號
  • 當新版本僅僅修正漏洞或者增強效率,仍然兼容前一版本代碼,則提高修訂號

默認情況下,npm install --save下載的都是最新版本,並且會在package.json文件里登記一個最優版本號,其形式如下所示:

"dependencies": { "express": "^4.10.0", "ejs": "~2.3.2" } 

可以看到,最優版本號在數字之前多出一個“標記”。當以后使用npm install按照package.json的這一部分來下載依賴包時,^意味着所下載的包有可能會有更高的次版本號或者修訂版本號,而~意味着有可能會有更高的修訂版本號。

鎖定依賴包的版本

如果所有的Node包都嚴格地符合語義化版本管理的規則,那么npm的最優版本號就能保證所下載的依賴包一定是與代碼兼容的。但問題是我們無法保證這一前提,如果想要保證用戶(或者其他開發人員)下載依賴包與我們的代碼絕對兼容,那么可以用下面兩種辦法來鎖定項目的依賴包的版本號。

回避最優版本號

最簡單最快捷的方法,就是不使用最優版本號。對於已經記錄在package.json里的版本號,只需把打頭的^~標記去掉即可。而新安裝依賴包時,則使用npm install --save-exact <package_name>或者npm install --save <package_name>@1.2.3,這樣package.json里就不會出現最優版本的標記。

這個方法雖然簡單,但是有個缺陷:無法鎖定次級依賴的版本號(依賴包的依賴包,等等)。比如說你的項目依賴某個特定版本的Backbone.js,你可以按照上面的方法在package.json里去掉最優版本的標記:

"dependencies": {
    "backbone": "1.2.3"   
}

而這個版本的Backbone有自己的package.json,里面記錄的依賴包使用的很可能還是最優版本號。比如Backbone依賴Underscore.js,你在開發時,npm為Backbone下載的可能是underscore@1.1.1,而當之后的某個時刻,Underscore有了更新,同一項目的開發人員或者你的包的使用者運行npm install時下載的可能就是underscore@1.2.0。大多數情況下,這不會有什么問題,但是萬一真的不兼容(或者你就是想要絕對安全),那么就得使用更加復雜一些的方法了。

使用npm shrinkwrap命令

現在問題的關鍵在於如何鎖定依賴之依賴的版本號。npm有一個命令來解決這個問題:npm shrinkwrap

比如說,你在開發某個Node項目時,進行到某個節點,一切都運行順利,說明目前所有的依賴包(以及更底層的依賴包)和你的代碼兼容得很好。這個時候,你就可以在項目文件夾下運行上面的這個命令。它會生成一個npm-shrinkwrap.json文件,記錄目前所有依賴包(及更底層依賴包)的版本信息。這樣當以后你(或者你的同事、你的用戶)運行npm install命令時,npm首先會找npm-shrinkwrap.json文件,依照其中的信息來准確地安裝每一個依賴包,只有當這個文件不存在時,npm才會使用package.json

在這之后開發的過程中,如果你想要更新某個依賴包,比如將Express從4.13.0更新到4.14.1,那么就只需npm install express@4.14.1;或者想要添加新的依賴包,比如Helmet,也只需npm install helmet。經過一段時間的測試與開發,當你確定這些新版本新安裝的依賴包與自己的代碼兼容后,就可以再次運行npm shrinkwrap命令來鎖定依賴包的版本。

本地安裝優於全局安裝

npm安裝依賴包時有兩種模式:本地安裝或者全局安裝。本地安裝表示該依賴包會被下載到當前項目的node_modules文件夾里,而全局變量則會把它安裝到系統級別的目錄里。比如用npm install -g typescript全局安裝typescript這個包后,我們就可以在系統的任何位置使用tsc命令來編譯TypeScript文件。這本身沒有什么錯,有些Node包的命令確實需要在任何位置都能使用,但全局安裝依賴包也有隱患:使用你的應用的用戶如果沒有全局安裝typescript怎么辦?或者如果她所安裝的版本不兼容怎么辦?

所以,安裝依賴包最好遵循以下實踐:

  1. 盡量不全局安裝依賴包,除非是typescript,grunt這種確實有需要的
  2. 所有的依賴包都應該本地安裝,即使是那些已經全局安裝過的

本地安裝的依賴包,其命令都位於當前項目的node_module/.bin文件夾下。package.json文件的"scripts"部分所使用的依賴包命令都會先去這個文件夾尋找。

例如,你的package.json里有這么一段:

"scripts": { "build:js": "tsc" } 

那么,當你運行npm run build:js時,npm會先去當前項目的node_module/.bin里尋找對應的執行文件,如果你沒有本地安裝,才會使用全局級別的命令。

結語

以上就是對npm如何管理項目的依賴包版本的一個簡單總結。主要涉及的知識點包括:語義化的版本號,最優版本號,兩種鎖定依賴包的方法,以及為什么本地安裝依賴包會優於全局安裝

轉載 https://www.jianshu.com/p/1470c5d7b8c3


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM