npm3 Non-determinism

在一些頁(yè)面的例子里是這么說(shuō)的:


如果你和你的開(kāi)發(fā)團(tuán)隊(duì)使用package.json,也通過(guò)npm install命令添加pkgs(像大多數(shù)使用npm團(tuán)隊(duì)做的),很可能會(huì)遇到這種情況:你本地的node_modules目錄和你同事的node_modules目錄不同,包括node_modules目錄在staging,testing或者生產(chǎn)服務(wù)上。

簡(jiǎn)單來(lái)說(shuō):npm3不是一個(gè)絕對(duì)的方式安裝依賴。
知道這個(gè)可能不太舒服,但是這篇文章我們會(huì)討論為什么會(huì)這樣,同時(shí)像你保證對(duì)你的應(yīng)用沒(méi)有影響,同時(shí)會(huì)告訴你如何創(chuàng)建一個(gè)單一的,一致的node_modules目錄。

例子:

讓我們回到幾個(gè)例子之前:


這個(gè)例子里,我們的應(yīng)用的package.json如下:

{
  "name": "example3",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "mod-a": "^1.0.0",
    "mod-c": "^1.0.0",
    "mod-d": "^1.0.0",
    "mod-e": "^1.0.0"
  }
}

npm install,我們?cè)诮K端里看到如下:


現(xiàn)在,假設(shè)我們團(tuán)隊(duì)里的開(kāi)發(fā)者決定完成一個(gè)特性需要將模塊A升級(jí)到v2.0,并且依賴于模塊B v2.0,而不是之前的模塊B v1.0

開(kāi)發(fā)者使用npm install命令來(lái)安裝新版本的Module A,并且保存到package.json:

npm install mod-a@2 --save

終端輸出如下:


現(xiàn)在看起來(lái)是這樣的:


假設(shè)開(kāi)發(fā)者完成了特性需要ModuleA的新版本并且推送應(yīng)用到測(cè)試服務(wù)上運(yùn)行了npm install在新的package.json

{
  "name": "example3",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "mod-a": "^2.0.0",
    "mod-c": "^1.0.0",
    "mod-d": "^1.0.0",
    "mod-e": "^1.0.0"
  }
}

測(cè)試服務(wù)日志如下:


圖形化如下:


什么鬼?這個(gè)目錄結(jié)構(gòu)和我們本地機(jī)器上的目錄結(jié)構(gòu)完全不一樣。咋的了這是?

記住:安裝順序很重要

當(dāng)開(kāi)發(fā)者使用npm install更新Module A,Module A v2.0是最后一個(gè)安裝的。因?yàn)殚_(kāi)發(fā)者是一開(kāi)始就在這個(gè)項(xiàng)目上使用npm install完成的,所有在package.json列出的的模塊已經(jīng)安裝在node_module目錄了。然后Module A v2.0 被安裝。
接著,Module B v1.0是頂級(jí)依賴因?yàn)镸odule A v1.0,然后因?yàn)镸odule E v1.0而讓Module B v1.0仍然在頂級(jí)依賴?yán)铩R驗(yàn)镸odule B仍然占著頂級(jí),導(dǎo)致其他版本的Module B不能在這,因此,ModuleBv2.0仍然是Module C和D的嵌套依賴,同樣也是Module A2.0的嵌套依賴。

讓我們想一下測(cè)試服務(wù)器上發(fā)生了什么。項(xiàng)目被推送到一個(gè)新目錄里。比如:預(yù)先不存在node_modules目錄,然后npm install執(zhí)行,大概通過(guò)部署腳本,從package.json里安裝依賴。

package.json現(xiàn)在已經(jīng)有了模塊A v2.0在里面,并且是按字母排序的(npm install命令強(qiáng)制的),現(xiàn)在是第一個(gè)安裝的,而不是最后一個(gè)。
當(dāng)模塊A是在一個(gè)干凈的node_modules里第一個(gè)安裝的,它的依賴當(dāng)然也是第一個(gè)候選在頂級(jí)位置。因此,Module B v2.0安裝在node_modules目錄的頂級(jí)。

現(xiàn)在,當(dāng)是時(shí)候安裝模塊E v1.0的時(shí)候,它的依賴模塊B v1.0,占不了頂級(jí)node_modules目錄了,自然就在Module E目錄下了。

不同的依賴樹(shù)結(jié)構(gòu)會(huì)對(duì)應(yīng)用有影響嗎?

不會(huì)!即使樹(shù)結(jié)構(gòu)不同,足夠的安裝和所有依賴項(xiàng)指向他們所有的依賴關(guān)系,等等。仍然擁有你所需要的一切,只是碰巧在不同的配置。

想要node_modules目錄保持一致,咋整?

npm install命令,當(dāng)使用唯一的package.json安裝依賴,產(chǎn)生的樹(shù)結(jié)構(gòu)是一樣的。因?yàn)閬?lái)自于package.json的安裝順序使用是一樣的。相同的安裝順序就能得到相同的樹(shù)結(jié)構(gòu)。

然后在改變package.json的時(shí)候可以放心的刪除掉node_modules,然后重新運(yùn)行npm install,就能保證樹(shù)結(jié)構(gòu)是一致的咯。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容