天天看點

node應用線上部署時鎖定包的依賴版本

我們使用node開發時,經常需要依賴一些子產品來完成功能需求,而我們所依賴的子產品也必然會依賴其他子產品,就這樣一級一級的依賴,而且這些依賴子產品并不為我們所控制。一個産品或項目的開發周期,少則幾個周,多則幾個月幾年。開發人員往往在一開始時下載下傳了依賴包發現能夠正常工作後,便一直在依賴包的目前版本上工作,然而線上上伺服器布屬時往往是根據依賴配置檔案,重新下載下傳依賴包。可這個時候依賴鍊中的包的開發者很可能已經将某個子產品更新了,而且并不能保證這些新的依賴包沒有bug。一旦依賴鍊上的某個包出現bug,可能對産品造成嚴重影響,而且這個時候往往無法找回開發時所用的正确依賴,以及依賴的依賴的版本。

我們來看一個經典的例子:

假設有包a依賴包b,包b依賴包c:

假設在開發時,我們運作<code>npm install a</code>得到以下的依賴鍊:

而在項目需要部署上線時,我們不可能把所有<code>node_modules</code>放到線上伺服器中,是以将項目代碼放到伺服器時,我們便會運作<code>npm install a</code>,而恰恰這階段,包b的版本更新到了<code>0.0.8</code>,是以我們在伺服器上得到的依賴鍊就是:

如果b的新版本有問題,這時就會對産品造成難以預估的損失。

是以我們推薦當開發環境中,所有依賴子產品都能正常工作時,便在部署到伺服器之前将依賴包的版本鎖住,這時候就運作這個指令:

我們會得到一個npm-shrinkwrap.json的檔案,這個檔案儲存了所有目前使用的依賴子產品的版本:

将這個檔案連同項目源碼一同部署到伺服器上,然後運作<code>npm install</code>這時候,npm會首先檢查有沒有npm-shrinkwrap.json檔案,有的話會根據該檔案中依賴包的版本以及resolve字段下載下傳依賴包,這樣就能夠保證線上環境與開發環境一緻。

這個檔案時根據我們目前項目中的<code>node_modules</code>中的子產品的目前版本生成的。<code>version</code>代表目前子產品版本,<code>from</code>表示的是package.json中對該依賴子產品的版本描述,<code>resolve</code>代表目前子產品的實際來源。

比如當你的package.json中對于某個依賴子產品有如下描述:

當<code>acorn</code>子產品安裝後,它的package.json檔案中會出現如下字段:

這時候運作<code>npm shrinkwrap</code>便會出現:

對于npm-shrinkwrap.json來說,這其中最重要的就是<code>resolve</code>字段。

如果要安裝新的依賴子產品,一定要使用<code>npm install --save 子產品</code>,這樣保證package.json與npm-shrinkwrap.json檔案同步更新。

<code>node_modules</code>中的子產品必須能夠包含package.json中的依賴子產品,如果node_modules中不存在package.json中指定的依賴子產品,運作<code>npm shrinkwrap</code>會報錯;如果node_modules中包含有package.json中未指定的子產品,根據官方說法是也會報錯,但根據我的實驗(windows7系統)并沒有報錯,npm-shrinkwrap.json會包含所有在node_modules中的子產品。

npm-shrinkwrap.json中并不會包含<code>devdependencies</code>字段中的子產品。

<a href="https://docs.npmjs.com/cli/shrinkwrap">npm-shrinkwrap-lock down dependency versions</a>