npm shrinkwrap
我們使用node開發時,經常需要依賴一些模塊來完成功能需求,而我們所依賴的模塊也必然會依賴其他模塊,就這樣一級一級的依賴,而且這些依賴模塊並不為我們所控制。一個產品或項目的開發周期,少則幾個周,多則幾個月幾年。開發人員往往在一開始時下載了依賴包發現能夠正常工作后,便一直在依賴包的當前版本上工作,然而在線上服務器布屬時往往是根據依賴配置文件,重新下載依賴包。可這個時候依賴鏈中的包的開發者很可能已經將某個模塊升級了,而且並不能保證這些新的依賴包沒有bug。一旦依賴鏈上的某個包出現bug,可能對產品造成嚴重影響,而且這個時候往往無法找回開發時所用的正確依賴,以及依賴的依賴的版本。
我們來看一個經典的例子:
假設有包A依賴包B,包B依賴包C:
//包A
{
"name": "A",
"version": "0.1.0",
"dependencies": {
"B": "<0.1.0"
}
}
//包B
{
"name": "B",
"version": "0.0.1",
"dependencies": {
"C": "<0.1.0"
}
}
//包C
{
"name": "C",
"version": "0.0.1"
}
假設在開發時,我們運行npm install A
得到以下的依賴鏈:
A@0.1.0
`-- B@0.0.1
`-- C@0.0.1
而在項目需要部署上線時,我們不可能把所有node_modules
放到線上服務器中,所以將項目代碼放到服務器時,我們便會運行npm install A
,而恰恰這階段,包B的版本更新到了0.0.8
,所以我們在服務器上得到的依賴鏈就是:
A@0.1.0
`-- B@0.0.8
`-- C@0.0.1
如果B的新版本有問題,這時就會對產品造成難以預估的損失。
所以我們推薦當開發環境中,所有依賴模塊都能正常工作時,便在部署到服務器之前將依賴包的版本鎖住,這時候就運行這個命令:
npm shrinkwrap
我們會得到一個npm-shrinkwrap.json的文件,這個文件保存了所有當前使用的依賴模塊的版本:
{
"name": "A",
"version": "0.1.0",
"dependencies": {
"B": {
"version": "0.0.1",
"from": "B@^0.0.1",
"resolved": "https://registry.npmjs.org/B/-/B-0.0.1.tgz",
"dependencies": {
"C": {
"version": "0.0.1",
"from": "org/C#v0.0.1",
"resolved": "git://github.com/org/C.git#5c380ae319fc4efe9e7f2d9c78b0faa588fd99b4"
}
}
}
}
}
將這個文件連同項目源碼一同部署到服務器上,然后運行npm install
這時候,npm會首先檢查有沒有npm-shrinkwrap.json文件,有的話會根據該文件中依賴包的版本以及resolve字段下載依賴包,這樣就能夠保證線上環境與開發環境一致。
from 與 resolve
這個文件時根據我們當前項目中的node_modules
中的模塊的當前版本生成的。version
代表當前模塊版本,from
表示的是package.json中對該依賴模塊的版本描述,resolve
代表當前模塊的實際來源。
比如當你的package.json中對於某個依賴模塊有如下描述:
"dependencies": {
"acorn": "^3.0.0",
....................................
}
當acorn
模塊安裝后,它的package.json文件中會出現如下字段:
"_from": "acorn@>=3.0.0 <4.0.0",
"_resolved": "https://registry.npmjs.org/acorn/-/acorn-3.2.0.tgz",
這時候運行npm shrinkwrap
便會出現:
"dependencies": {
"acorn": {
"version": "3.2.0",
"from": "acorn@>=3.0.0 <4.0.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-3.2.0.tgz"
},
對於npm-shrinkwrap.json來說,這其中最重要的就是resolve
字段。
使用npm shrinkwrap的注意事項
- 如果要安裝新的依賴模塊,一定要使用
npm install --save 模塊
,這樣保證package.json與npm-shrinkwrap.json文件同步更新。 node_modules
中的模塊必須能夠包含package.json中的依賴模塊,如果node_modules中不存在package.json中指定的依賴模塊,運行npm shrinkwrap
會報錯;如果node_modules中包含有package.json中未指定的模塊,根據官方說法是也會報錯,但根據我的實驗(windows7系統)並沒有報錯,npm-shrinkwrap.json會包含所有在node_modules中的模塊。- npm-shrinkwrap.json中並不會包含
devDependencies
字段中的模塊。