**npm管理機制**
Nodejs
成功離不開 npm
優秀的依賴管理系統。在介紹整個依賴系統以前,必需要了解 npm
如何管理依賴包的版本,本章將介紹 npm包
的版本發佈規範、如何管理各類依賴包的版本以及一些關於包版本的最佳實踐。html
你能夠執行 npm view package version
查看某個 package
的最新版本。node
執行 npm view conard versions
查看某個 package
在npm服務器上全部發布過的版本。react
執行 npm ls
可查看當前倉庫依賴樹上全部包的版本信息。git
npm包
中的模塊版本都須要遵循 SemVer
規範——由 Github
起草的一個具備指導意義的,統一的版本號表示規則。實際上就是 Semantic Version
(語義化版本)的縮寫。github
SemVer規範官網: semver.org/docker
SemVer
規範的標準版本號採用 X.Y.Z
的格式,其中 X、Y 和 Z 爲非負的整數,且禁止在數字前方補零。X 是主版本號、Y 是次版本號、而 Z 爲修訂號。每一個元素必須以數值來遞增。npm
major
):當你作了不兼容的API 修改minor
):當你作了向下兼容的功能性新增patch
):當你作了向下兼容的問題修正。例如:1.9.1 -> 1.10.0 -> 1.11.0
json
當某個版本改動比較大、並不是穩定並且可能沒法知足預期的兼容性需求時,你可能要先發佈一個先行版本。緩存
先行版本號能夠加到「主版本號.次版本號.修訂號」的後面,先加上一個鏈接號再加上一連串以句點分隔的標識符和版本編譯信息。安全
alpha
):beta
):rc
: 即 Release candiate
下面咱們來看看 React
的歷史版本:
可見是嚴格按照 SemVer
規範來發版的:
主版本號.次版本號.修訂號
格式命名16.8.0 -> 16.8.1 -> 16.8.2
alpha
、beta
、rc
等先行版本在修改 npm
包某些功能後一般須要發佈一個新的版本,咱們一般的作法是直接去修改 package.json
到指定版本。若是操做失誤,很容易形成版本號混亂,咱們能夠藉助符合 Semver
規範的命令來完成這一操做:
npm version patch
: 升級修訂版本號npm version minor
: 升級次版本號npm version major
: 升級主版本號在開發中確定少不了對一些版本號的操做,若是這些版本號符合 SemVer
規範 ,咱們能夠藉助用於操做版本的npm包semver
來幫助咱們進行比較版本大小、提取版本信息等操做。
Npm 也使用了該工具來處理版本相關的工做。
npm install semver
複製代碼
semver.gt('1.2.3', '9.8.7') // false
semver.lt('1.2.3', '9.8.7') // true
複製代碼
semver.valid('1.2.3') // '1.2.3'
semver.valid('a.b.c') // null
複製代碼
semver.valid(semver.coerce('v2')) // '2.0.0'
semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7'
複製代碼
semver.clean(' =v1.2.3 ') // '1.2.3'
semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
semver.minVersion('>=1.0.0') // '1.0.0'
複製代碼
以上都是semver最多見的用法,更多詳細內容能夠查看 semver文檔:github.com/npm/node-se…
咱們常常看到,在 package.json
中各類依賴的不一樣寫法:
"dependencies": {
"signale": "1.4.0",
"figlet": "*",
"react": "16.x",
"table": "~5.4.6",
"yargs": "^14.0.0"
}
複製代碼
前面三個很容易理解:
"signale": "1.4.0"
: 固定版本號"figlet": "*"
: 任意版本(>=0.0.0
)"react": "16.x"
: 匹配主要版本(>=16.0.0 <17.0.0
)"react": "16.3.x"
: 匹配主要版本和次要版本(>=16.3.0 <16.4.0
)再來看看後面兩個,版本號中引用了 ~
和 ^
符號:
~
: 當安裝依賴時獲取到有新版本時,安裝到 x.y.z
中 z
的最新的版本。即保持主版本號、次版本號不變的狀況下,保持修訂號的最新版本。^
: 當安裝依賴時獲取到有新版本時,安裝到 x.y.z
中 y
和 z
都爲最新版本。 即保持主版本號不變的狀況下,保持次版本號、修訂版本號爲最新版本。在 package.json
文件中最多見的應該是 "yargs": "^14.0.0"
這種格式的 依賴, 由於咱們在使用 npm install package
安裝包時,npm
默認安裝當前最新版本,而後在所安裝的版本號前加 ^
號。
注意,當主版本號爲 0
的狀況,會被認爲是一個不穩定版本,狀況與上面不一樣:
0
: ^0.0.z
、~0.0.z
都被看成固定版本,安裝依賴時均不會發生變化。0
: ^0.y.z
表現和 ~0.y.z
相同,只保持修訂號爲最新版本。1.0.0 的版本號用於界定公共 API。當你的軟件發佈到了正式環境,或者有穩定的API時,就能夠發佈1.0.0版本了。因此,當你決定對外部發佈一個正式版本的npm包時,把它的版本標爲1.0.0。
實際開發中,常常會由於各類依賴不一致而產生奇怪的問題,或者在某些場景下,咱們不但願依賴被更新,建議在開發中使用 package-lock.json
。
鎖定依賴版本意味着在咱們不手動執行更新的狀況下,每次安裝依賴都會安裝固定版本。保證整個團隊使用版本號一致的依賴。
每次安裝固定版本,無需計算依賴版本範圍,大部分場景下能大大加速依賴安裝時間。
使用 package-lock.json 要確保npm的版本在5.6以上,由於在5.0 - 5.6中間,對 package-lock.json的處理邏輯進行過幾回更新,5.6版本後處理邏輯逐漸穩定。
關於 package-lock.json
詳細的結構,咱們會在後面的章節進行解析。
咱們的目的是保證團隊中使用的依賴一致或者穩定,而不是永遠不去更新這些依賴。實際開發場景下,咱們雖然不須要每次都去安裝新的版本,仍然須要定時去升級依賴版本,來讓咱們享受依賴包升級帶來的問題修復、性能提高、新特性更新。
使用 npm outdated
能夠幫助咱們列出有哪些尚未升級到最新版本的依賴:
執行 npm update
會升級全部的紅色依賴。
1.0.0
。主版本號.次版本號.修訂號
格式命名alpha、beta、rc
等先行版本npm
包,此時建議把版本前綴改成~
,若是鎖定的話每次子依賴更新都要對主工程的依賴進行升級,很是繁瑣,若是對子依賴徹底信任,直接開啓^
每次升級到最新版本。docker
線上,本地還在進行子依賴開發和升級,在docker
版本發佈前要鎖定全部依賴版本,確保本地子依賴發佈後線上不會出問題。npm
的版本在5.6
以上,確保默認開啓 package-lock.json
文件。npm inatall
後,將 package-lock.json
提交到遠程倉庫。不要直接提交 node_modules
到遠程倉庫。npm update
升級依賴,並提交 lock
文件確保其餘成員同步更新依賴,不要手動更改 lock
文件。package.json
文件的依賴版本,執行 npm install
npm install package@version
(改動package.json
不會對依賴進行降級)lock
文件npm install
大概會通過上面的幾個流程,這一章就來說一講各個流程的實現細節、發展以及爲什麼要這樣實現。
咱們都知道,執行 npm install
後,依賴包被安裝到了 node_modules
,下面咱們來具體瞭解下,npm
將依賴包安裝到 node_modules
的具體機制是什麼。
在 npm
的早期版本, npm
處理依賴的方式簡單粗暴,以遞歸的形式,嚴格按照 package.json
結構以及子依賴包的 package.json
結構將依賴安裝到他們各自的 node_modules
中。直到有子依賴包不在依賴其餘模塊。
舉個例子,咱們的模塊 my-app
如今依賴了兩個模塊:buffer
、ignore
:
{
"name": "my-app",
"dependencies": {
"buffer": "^5.4.3",
"ignore": "^5.1.4",
}
}
複製代碼
ignore
是一個純 JS
模塊,不依賴任何其餘模塊,而 buffer
又依賴了下面兩個模塊:base64-js
、 ieee754
。
{
"name": "buffer",
"dependencies": {
"base64-js": "^1.0.2",
"ieee754": "^1.1.4"
}
}
複製代碼
那麼,執行 npm install
後,獲得的 node_modules
中模塊目錄結構就是下面這樣的:
這樣的方式優勢很明顯, node_modules
的結構和 package.json
結構一一對應,層級結構明顯,而且保證了每次安裝目錄結構都是相同的。
可是,試想一下,若是你依賴的模塊很是之多,你的 node_modules
將很是龐大,嵌套層級很是之深:
Windows
系統中,文件路徑最大長度爲260個字符,嵌套層級過深可能致使不可預知的問題。爲了解決以上問題,NPM
在 3.x
版本作了一次較大更新。其將早期的嵌套結構改成扁平結構:
node_modules
根目錄。仍是上面的依賴結構,咱們在執行 npm install
後將獲得下面的目錄結構:
此時咱們若在模塊中又依賴了 base64-js@1.0.1
版本:
{
"name": "my-app",
"dependencies": {
"buffer": "^5.4.3",
"ignore": "^5.1.4",
"base64-js": "1.0.1",
}
}
複製代碼
node_modules
下安裝該模塊。此時,咱們在執行 npm install
後將獲得下面的目錄結構:
對應的,若是咱們在項目代碼中引用了一個模塊,模塊查找流程以下:
node_modules
路徑下搜素node_modules
路徑下搜索node_modules
假設咱們又依賴了一個包 buffer2@^5.4.3
,而它依賴了包 base64-js@1.0.3
,則此時的安裝結構是下面這樣的:
因此 npm 3.x
版本並未徹底解決老版本的模塊冗餘問題,甚至還會帶來新的問題。
試想一下,你的APP假設沒有依賴 base64-js@1.0.1
版本,而你同時依賴了依賴不一樣 base64-js
版本的 buffer
和 buffer2
。因爲在執行 npm install
的時候,按照 package.json
裏依賴的順序依次解析,則 buffer
和 buffer2
在 package.json
的放置順序則決定了 node_modules
的依賴結構:
先依賴buffer2
:
先依賴buffer
:
另外,爲了讓開發者在安全的前提下使用最新的依賴包,咱們在 package.json
一般只會鎖定大版本,這意味着在某些依賴包小版本更新後,一樣可能形成依賴結構的改動,依賴結構的不肯定性可能會給程序帶來不可預知的問題。
爲了解決 npm install
的不肯定性問題,在 npm 5.x
版本新增了 package-lock.json
文件,而安裝方式還沿用了 npm 3.x
的扁平化的方式。
package-lock.json
的做用是鎖定依賴結構,即只要你目錄下有 package-lock.json
文件,那麼你每次執行 npm install
後生成的 node_modules
目錄結構必定是徹底相同的。
例如,咱們有以下的依賴結構:
{
"name": "my-app",
"dependencies": {
"buffer": "^5.4.3",
"ignore": "^5.1.4",
"base64-js": "1.0.1",
}
}
複製代碼
在執行 npm install
後生成的 package-lock.json
以下:
{
"name": "my-app",
"version": "1.0.0",
"dependencies": {
"base64-js": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.0.1.tgz",
"integrity": "sha1-aSbRsZT7xze47tUTdW3i/Np+pAg="
},
"buffer": {
"version": "5.4.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz",
"integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==",
"requires": {
"base64-js": "^1.0.2",
"ieee754": "^1.1.4"
},
"dependencies": {
"base64-js": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
}
}
},
"ieee754": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
},
"ignore": {
"version": "5.1.4",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz",
"integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A=="
}
}
}
複製代碼
咱們來具體看看上面的結構:
最外面的兩個屬性 name
、version
同 package.json
中的 name
和 version
,用於描述當前包名稱和版本。
dependencies
是一個對象,對象和 node_modules
中的包結構一一對應,對象的 key
爲包名稱,值爲包的一些描述信息:
version
:包版本 —— 這個包當前安裝在 node_modules
中的版本resolved
:包具體的安裝來源integrity
:包 hash
值,基於 Subresource Integrity
來驗證已安裝的軟件包是否被改動過、是否已失效requires
:對應子依賴的依賴,與子依賴的 package.json
中 dependencies
的依賴項相同。dependencies
:結構和外層的 dependencies
結構相同,存儲安裝在子依賴 node_modules
中的依賴包。這裏注意,並非全部的子依賴都有 dependencies
屬性,只有子依賴的依賴和當前已安裝在根目錄的 node_modules
中的依賴衝突以後,纔會有這個屬性。
例如,回顧下上面的依賴關係:
咱們在 my-app
中依賴的 base64-js@1.0.1
版本與 buffer
中依賴的 base64-js@^1.0.2
發生衝突,因此 base64-js@1.0.1
須要安裝在 buffer
包的 node_modules
中,對應了 package-lock.json
中 buffer
的 dependencies
屬性。這也對應了 npm
對依賴的扁平化處理方式。
因此,根據上面的分析, package-lock.json
文件 和 node_modules
目錄結構是一一對應的,即項目目錄下存在 package-lock.json
可讓每次安裝生成的依賴目錄結構保持相同。
另外,項目中使用了 package-lock.json
能夠顯著加速依賴安裝時間。
咱們使用 npm i --timing=true --loglevel=verbose
命令能夠看到 npm install
的完整過程,下面咱們來對比下使用 lock
文件和不使用 lock
文件的差異。在對比前先清理下npm
緩存。
不使用 lock
文件:
使用 lock
文件:
可見, package-lock.json
中已經緩存了每一個包的具體版本和下載連接,不須要再去遠程倉庫進行查詢,而後直接進入文件完整性校驗環節,減小了大量網絡請求。
開發系統應用時,建議把 package-lock.json
文件提交到代碼版本倉庫,從而保證全部團隊開發者以及 CI
環節能夠在執行 npm install
時安裝的依賴版本都是一致的。
在開發一個 npm
包 時,你的 npm
包 是須要被其餘倉庫依賴的,因爲上面咱們講到的扁平安裝機制,若是你鎖定了依賴包版本,你的依賴包就不能和其餘依賴包共享同一 semver
範圍內的依賴包,這樣會形成沒必要要的冗餘。因此咱們不該該把package-lock.json
文件發佈出去( npm
默認也不會把 package-lock.json
文件發佈出去)。
在執行 npm install
或 npm update
命令下載依賴後,除了將依賴包安裝在node_modules
目錄下外,還會在本地的緩存目錄緩存一份。
經過 npm config get cache
命令能夠查詢到:在 Linux
或 Mac
默認是用戶主目錄下的 .npm/_cacache
目錄。
在這個目錄下又存在兩個目錄:content-v2
、index-v5
,content-v2
目錄用於存儲 tar
包的緩存,而index-v5
目錄用於存儲tar
包的 hash
。
npm 在執行安裝時,能夠根據 package-lock.json
中存儲的 integrity、version、name
生成一個惟一的 key
對應到 index-v5
目錄下的緩存記錄,從而找到 tar
包的 hash
,而後根據 hash
再去找緩存的 tar
包直接使用。
咱們能夠找一個包在緩存目錄下搜索測試一下,在 index-v5
搜索一下包路徑:
grep "https://registry.npmjs.org/base64-js/-/base64-js-1.0.1.tgz" -r index-v5
複製代碼
而後咱們將json格式化:
{
"key": "pacote:version-manifest:https://registry.npmjs.org/base64-js/-/base64-js-1.0.1.tgz:sha1-aSbRsZT7xze47tUTdW3i/Np+pAg=",
"integrity": "sha512-C2EkHXwXvLsbrucJTRS3xFHv7Mf/y9klmKDxPTE8yevCoH5h8Ae69Y+/lP+ahpW91crnzgO78elOk2E6APJfIQ==",
"time": 1575554308857,
"size": 1,
"metadata": {
"id": "base64-js@1.0.1",
"manifest": {
"name": "base64-js",
"version": "1.0.1",
"engines": {
"node": ">= 0.4"
},
"dependencies": {},
"optionalDependencies": {},
"devDependencies": {
"standard": "^5.2.2",
"tape": "4.x"
},
"bundleDependencies": false,
"peerDependencies": {},
"deprecated": false,
"_resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.0.1.tgz",
"_integrity": "sha1-aSbRsZT7xze47tUTdW3i/Np+pAg=",
"_shasum": "6926d1b194fbc737b8eed513756de2fcda7ea408",
"_shrinkwrap": null,
"bin": null,
"_id": "base64-js@1.0.1"
},
"type": "finalized-manifest"
}
}
複製代碼
上面的 _shasum
屬性 6926d1b194fbc737b8eed513756de2fcda7ea408
即爲 tar
包的 hash
, hash
的前幾位 6926
即爲緩存的前兩層目錄,咱們進去這個目錄果真找到的壓縮後的依賴包:
以上的緩存策略是從 npm v5 版本開始的,在 npm v5 版本以前,每一個緩存的模塊在 ~/.npm 文件夾中以模塊名的形式直接存儲,儲存結構是{cache}/{name}/{version}。
npm
提供了幾個命令來管理緩存數據:
npm cache add
:官方解釋說這個命令主要是 npm
內部使用,可是也能夠用來手動給一個指定的 package 添加緩存。npm cache clean
:刪除緩存目錄下的全部數據,爲了保證緩存數據的完整性,須要加上 --force
參數。npm cache verify
:驗證緩存數據的有效性和完整性,清理垃圾數據。基於緩存數據,npm 提供了離線安裝模式,分別有如下幾種:
--prefer-offline
: 優先使用緩存數據,若是沒有匹配的緩存數據,則從遠程倉庫下載。--prefer-online
: 優先使用網絡數據,若是網絡數據請求失敗,再去請求緩存數據,這種模式能夠及時獲取最新的模塊。--offline
: 不請求網絡,直接使用緩存數據,一旦緩存數據不存在,則安裝失敗。上面咱們屢次提到了文件完整性,那麼什麼是文件完整性校驗呢?
在下載依賴包以前,咱們通常就能拿到 npm
對該依賴包計算的 hash
值,例如咱們執行 npm info
命令,緊跟 tarball
(下載連接) 的就是 shasum
(hash
) :
用戶下載依賴包到本地後,須要肯定在下載過程當中沒有出現錯誤,因此在下載完成以後須要在本地在計算一次文件的 hash
值,若是兩個 hash
值是相同的,則確保下載的依賴是完整的,若是不一樣,則進行從新下載。
好了,咱們再來總體總結下上面的流程:
檢查 .npmrc
文件:優先級爲:項目級的 .npmrc
文件 > 用戶級的 .npmrc
文件> 全局級的 .npmrc
文件 > npm 內置的 .npmrc
文件
檢查項目中有無 lock
文件。
無 lock
文件:
從 npm
遠程倉庫獲取包信息
根據 package.json
構建依賴樹,構建過程:
構建依賴樹時,無論其是直接依賴仍是子依賴的依賴,優先將其放置在 node_modules
根目錄。
當遇到相同模塊時,判斷已放置在依賴樹的模塊版本是否符合新模塊的版本範圍,若是符合則跳過,不符合則在當前模塊的 node_modules
下放置該模塊。
注意這一步只是肯定邏輯上的依賴樹,並不是真正的安裝,後面會根據這個依賴結構去下載或拿到緩存中的依賴包
在緩存中依次查找依賴樹中的每一個包
不存在緩存:
從 npm
遠程倉庫下載包
校驗包的完整性
校驗不經過:
從新下載
校驗經過:
將下載的包複製到 npm
緩存目錄
將下載的包按照依賴結構解壓到 node_modules
存在緩存:將緩存按照依賴結構解壓到 node_modules
將包解壓到 node_modules
生成 lock
文件
有 lock
文件:
檢查 package.json
中的依賴版本是否和 package-lock.json
中的依賴有衝突。
若是沒有衝突,直接跳過獲取包信息、構建依賴樹過程,開始在緩存中查找包信息,後續過程相同
上面的過程簡要描述了 npm install
的大概過程,這個過程還包含了一些其餘的操做,例如執行你定義的一些生命週期函數,你能夠執行 npm install package --timing=true --loglevel=verbose
來查看某個包具體的安裝流程和細節。
yarn
是在 2016
年發佈的,那時 npm
還處於 V3
時期,那時候尚未 package-lock.json
文件,就像上面咱們提到的:不穩定性、安裝速度慢等缺點常常會受到廣大開發者吐槽。此時,yarn
誕生:
上面是官網提到的 yarn
的優勢,在那個時候仍是很是吸引人的。固然,後來 npm
也意識到了本身的問題,進行了不少次優化,在後面的優化(lock
文件、緩存、默認-s...)中,咱們多多少少能看到 yarn
的影子,可見 yarn
的設計仍是很是優秀的。
yarn
也是採用的是 npm v3
的扁平結構來管理依賴,安裝依賴後默認會生成一個 yarn.lock
文件,仍是上面的依賴關係,咱們看看 yarn.lock
的結構:
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
base64-js@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.0.1.tgz#6926d1b194fbc737b8eed513756de2fcda7ea408"
integrity sha1-aSbRsZT7xze47tUTdW3i/Np+pAg=
base64-js@^1.0.2:
version "1.3.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
buffer@^5.4.3:
version "5.4.3"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115"
integrity sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==
dependencies:
base64-js "^1.0.2"
ieee754 "^1.1.4"
ieee754@^1.1.4:
version "1.1.13"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"
integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==
ignore@^5.1.4:
version "5.1.4"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf"
integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==
複製代碼
可見其和 package-lock.json
文件仍是比較相似的,還有一些區別就是:
package-lock.json
使用的是 json
格式,yarn.lock
使用的是一種自定義格式yarn.lock
中子依賴的版本號不是固定的,意味着單獨又一個 yarn.lock
肯定不了 node_modules
目錄結構,還須要和 package.json
文件進行配合。而 package-lock.json
只須要一個文件便可肯定。yarn
的緩策略看起來和 npm v5
以前的很像,每一個緩存的模塊被存放在獨立的文件夾,文件夾名稱包含了模塊名稱、版本號等信息。使用命令 yarn cache dir
能夠查看緩存數據的目錄:
yarn
默認使用prefer-online
模式,即優先使用網絡數據,若是網絡數據請求失敗,再去請求緩存數據。