JavaScript包管理器實(shí)例比較分析

這篇文章主要講解了“JavaScript包管理器實(shí)例比較分析”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“JavaScript包管理器實(shí)例比較分析”吧!

10年積累的成都網(wǎng)站制作、成都做網(wǎng)站經(jīng)驗(yàn),可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先制作網(wǎng)站后付款的網(wǎng)站建設(shè)流程,更有元寶免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

JavaScript包管理器實(shí)例比較分析

包管理器領(lǐng)域的三個主要參與者:

  • npm

  • Yarn

  • 高性能 npm (pnpm)

實(shí)際上我們已經(jīng)在所有包管理器中實(shí)現(xiàn)了基本相似的功能,因此您很可能會根據(jù)非功能性要求來決定使用哪個包管理器,例如安裝速度、存儲消耗或?qū)嶋H情況。

當(dāng)然,您選擇使用每個包管理器的方式會有所不同,但它們都有基本一致的概念。以上這些包管理器都可以執(zhí)行以下指令:

  • 讀寫數(shù)據(jù)

  • 批量安裝或更新所有依賴項(xiàng)

  • 添加、更新和刪除依賴項(xiàng)

  • 運(yùn)行腳本

  • 發(fā)布包

然而盡管如此,包管理器在底層還是有所不同的。傳統(tǒng)上 npmYarn 將依賴項(xiàng)安裝在一個平鋪的node_modules文件夾中。(這里注意先后順序,是 yarn 先平鋪的,之前 npm 是遞歸)。但是平鋪也會造成一系列的安全問題。

  • 依賴結(jié)構(gòu)的不確定性。

  • 扁平化算法本身的復(fù)雜性很高,耗時較長。

  • 項(xiàng)目中仍然可以非法訪問

  • 有聲明過依賴的包

因此,pnpmnode_modules 文件夾中引入了一些新概念來更高效的存儲依賴,。Yarn Berry 甚至通過完全放棄 node_modules 的 (PnP) 模式(另一個文章會具體說明)來走得更遠(yuǎn)。

JavaScript package簡史


最早發(fā)布的包管理器是 npm,早在 2010 年 1 月。它就確立了今天包管理器工作的核心原則。但是既然 npm 已經(jīng)存在 10 多年了,為什么還有其他選擇?以下是出現(xiàn)這種情況的一些關(guān)鍵原因:

  • node_modules 文件夾結(jié)構(gòu)的依賴關(guān)系解析算法不同(嵌套 & 平鋪、node_modules vs. PnP mode)

  • 依賴提升方式不同(hoisting

  • locking 格式不同(性能都不同,比如 yarn 自己寫的那一套)

  • 磁盤存儲包文件方式不同(空間效率不同)

  • 多包項(xiàng)目(又名 workspaces)的支持不同,這會影響 monorepos 的可維護(hù)性和速度

  • 新工具和命令的需求不同(通過插件和社區(qū)工具對可擴(kuò)展性的需求不同)

  • 可配置性和靈活性不同

讓我們深入了解一下 npm 崛起后這些方面如何確定的歷史,Yarn Classic 如何解決其中的一些問題,pnpm如何擴(kuò)展這些概念,以及 Yarn Berry 作為 Yarn Classic 的繼任者如何打破這些傳統(tǒng)的概念和流程。

先驅(qū)者 npm

npm 是包管理器的鼻祖。許多人錯誤地認(rèn)為 npm 是“Node package manager”的首字母縮寫詞,但事實(shí)并非如此。

它的發(fā)布構(gòu)成了一場革命,因?yàn)樵诖酥?,?xiàng)目依賴項(xiàng)都是手動下載和管理的。npm 引入了諸如文件及其元數(shù)據(jù)字段、將依賴項(xiàng)存儲在node_modules, 自定義腳本, 公共和私有包等等。

2020 年,GitHub 收購了 npm,所以原則上 npm 現(xiàn)在歸微軟管理。在撰寫本文時,最新的主要版本是 v8,于 2021 年 10 月發(fā)布。

創(chuàng)新者 Yarn Classic

在 2016 年 10 月,F(xiàn)acebook 宣布與 Google 和其他一些公司合作開發(fā)一個新的包管理器(engineering.fb.com/2016/10/11/…),以解決 npm 當(dāng)時存在的一致性、安全性和性能問題。他們將替代品命名為Yarn。

盡管 Yarn 還是基于 npm 的許多概念和流程來架構(gòu)設(shè)計(jì)的,但 Yarn 還是對包管理器領(lǐng)域產(chǎn)生了重大影響。與 npm 相比,Yarn 并行化操作以加快安裝過程,這一直是 npm 早期版本的主要痛點(diǎn)。

Yarn 為讀寫、安全性和性能設(shè)定了更高的標(biāo)準(zhǔn),還發(fā)明了許多概念(后來npm也為此做了很多改進(jìn)),包括:

  • monorepo 支持

  • 緩存安裝

  • 離線下載

  • 文件鎖(Locking

Yarn v1 于 2020 年進(jìn)入維護(hù)模式 。從那時起,v1.x 系列被認(rèn)為是舊版,并更名為 Yarn Classic。它的繼任者 Yarn v2 (Berry) 現(xiàn)在是更加活躍的開發(fā)分支。

更高效的pnpm

pnpm 的第 1 版由 Zoltan Kochan于 2017 年發(fā)布。它是 npm 的替代品,所以如果你有一個 npm 項(xiàng)目,你可以馬上使用 pnpm!

創(chuàng)建 pnpm 的主要原因是 npmYarn 對于跨項(xiàng)目使用的依賴項(xiàng)存儲結(jié)構(gòu)非常冗余。盡管 Yarn Classicnpm 具有速度優(yōu)勢,但它使用相同的依賴解析方法,這對 pnpm 來說是不行的:npmYarn Classic 使用 hoisting 來平鋪他們的 node_modules.

pnpm 沒有優(yōu)化之前的結(jié)構(gòu),而是引入了另一種依賴解決策略:內(nèi)容尋址的一種存儲結(jié)構(gòu)。此方法生成的 node_modules 文件夾其實(shí)是依賴于全局存儲在主文件夾上的 ~/.pnpm-store/ 目錄。每個版本的依賴項(xiàng)都物理形式存儲在該目錄文件夾中一次,構(gòu)成單一的源地址來節(jié)省相當(dāng)多的磁盤空間。

node_modules 結(jié)構(gòu)是通過使用 symlinks 創(chuàng)建依賴關(guān)系的嵌套結(jié)構(gòu)(其中文件夾內(nèi)每個文件/包都是通過硬鏈接存儲)官方文檔中的下圖闡明了這一點(diǎn)。(待填坑:軟硬鏈接)

JavaScript包管理器實(shí)例比較分析

2021 年報(bào)告中可見 pnpm 的影響力:因?yàn)樗麄冊趦?nèi)容可尋址存儲方面的創(chuàng)新,競爭對手都希望采用 pnpm 的概念,比如象征性鏈接的結(jié)構(gòu)和包的高效磁盤管理。

Yarn (v2, Berry),用 Plug'n'Play 重新發(fā)明的輪子

Yarn 2于 2020 年 1 月發(fā)布,被宣傳為原始 Yarn 的重大升級。Yarn 團(tuán)隊(duì)將其稱為 Yarn Berry 以更明顯地表明它本質(zhì)上是一個具有新的代碼庫和新的原則規(guī)范的新包管理器。

Yarn Berry 的主要創(chuàng)新是其即插即用 (PnP)方法,它是作為修復(fù)node_modules的策略。不是生成node_modules 的策略,而是生成一個帶有依賴查找表的文件 .pnp.cjs,因?yàn)樗菃蝹€文件而不是嵌套的文件夾結(jié)構(gòu),所以可以更有效地處理依賴。此外,每個包都以zip 文件的形式存儲在文件夾內(nèi)來替代 .yarn/cache/,占用的磁盤空間也比 node_modules 少。

所有這些變化如此之快以至于在發(fā)布后引起了很大的爭議。PnP 這種破壞性的重大更改要求維護(hù)者更新他們現(xiàn)有的包以便與其兼容。默認(rèn)情況下使用全新的 PnP 方法并且恢復(fù)到 node_modules 最初并不簡單,這導(dǎo)致許多知名開發(fā)人員沒有加入其中的考慮且公開批評 Yarn 2。

此后,Yarn Berry 團(tuán)隊(duì)在其后續(xù)版本中解決了許多問題。為了解決 PnP 的不兼容問題,團(tuán)隊(duì)提供了方法來輕松更改默認(rèn)操作模式。在node_modules插件的幫助下,切換回傳統(tǒng)  node_modules 方法只需要一行配置。

此外,隨著時間的推移,JavaScript 生態(tài)系統(tǒng)為 PnP 提供了越來越多的支持,正如您在此兼容性表中所見,一些大型項(xiàng)目已經(jīng)開始采用 Yarn Berry。

盡管 Yarn Berry 還很年輕,但它也已經(jīng)對包管理器領(lǐng)域產(chǎn)生了影響——pnpm 在 2020 年末采用了PnP 方法。

安裝工作流程


首先必須在每個開發(fā)人員的本地和 CI/CD 系統(tǒng)上安裝包管理器。

npm

npmNode.js 一起提供,因此不需要額外的步驟。除了為您的操作系統(tǒng)下載Node.js 安裝程序外,使用 CLI 工具管理軟件版本已成為一種常見做法。在 Node 的上下文中,Node Version Manager (nvm) 或 Volta 已成為非常方便的實(shí)用程序。

Yarn Classic 和 Yarn Berry

您可以通過不同的方式安裝 Yarn 1,例如,作為 npm 包來安裝:.$ npm i -g yarn

要從Yarn Classic 遷移到 Yarn Berry,推薦的方法是:

  • 安裝或更新 Yarn Classic 到最新的版本

  • 使用命令升級到最新的現(xiàn)代版本

    yarn set version berry

但是,在此推薦的安裝 Yarn Berry方法是通過 Corepack。

Corepack是由 Yarn Berry 的開發(fā)者創(chuàng)建的。該計(jì)劃最初被命名為包管理器管理器(pmm) ?,并在 LTS v16 中與 Node 合并。

在 Corepack 的幫助下,因?yàn)?Node 包含 Yarn Classic、Yarn Berrypnpm 二進(jìn)制文件所以您不必“單獨(dú)”安裝的 npm 的替代包管理器。這些墊片允許用戶運(yùn)行 Yarn 和 pnpm 命令而無需先顯式安裝它們,也不會弄亂 Node 發(fā)行版。

Corepack 預(yù)裝了 Node.js ≥ v16.9.0。但是,對于較舊的 Node 版本,您可以使用??

npm install -g corepack

在使用之前先啟用 Corepack。該示例顯示了如何在 Yarn Berry v3.1.1 中激活它。

# you need to opt-in first
$ corepack enable
# shim installed but concrete version needs to activated
$ corepack prepare yarn@3.1.1 --activate

pnpm

您可以將 pnpm 作為 npm包來安裝: $ npm i -g pnpm。您還可以使用 Corepack 安裝 pnpm :

$ corepack prepare pnpm@6.24.2 --activate

項(xiàng)目結(jié)構(gòu)


在本節(jié)中,您將一目了然地看到不同包管理器的主要特征。您可以輕松發(fā)現(xiàn)配置特定包管理器涉及哪些文件,以及哪些文件是由安裝步驟生成的。

所有包管理器都將所有重要的元信息存儲在項(xiàng)目清單package.json文件中。 此外,根級別的配置文件可以被用來設(shè)置不同的私有包或者不同的依賴項(xiàng)解析配置。

在安裝步驟中,依賴項(xiàng) dependencies 被存儲在文件結(jié)構(gòu)中,例如 node_modules 并生成鎖定文件 locking。本節(jié)不考慮工作區(qū)設(shè)置,因此所有示例僅顯示存儲依賴項(xiàng)的單個位置。

npm

使用$ npm install 或較短的 $ npm i 會生成一個 package-lock.json 文件和一個 node_modules 文件夾。還有 .npmrc 這種可配置的文件可以放在根級別目錄里面。有關(guān) locking 文件的更多信息,請參閱下一節(jié)。

.
├── node_modules/
├── .npmrc
├── package-lock.json
└── package.json

yarn

運(yùn)行 $ yarn 會創(chuàng)建一個 yarn.lock 文件和一個 node_modules 文件夾。.yarnrc 文件也可以是配置的選項(xiàng),Yarn Classic 也支持 .npmrc 文件。或者可以使用緩存文件夾 .yarn/cache/ 和本地存儲的最近的 Yarn Classic 版本 .yarn/releases/

.
├── .yarn/
│   ├── cache/
│   └── releases/
│       └── yarn-1.22.17.cjs
├── node_modules/
├── .yarnrc
├── package.json
└── yarn.lock

yarn berry: node_modules

因?yàn)檫@種特殊的安裝模式,比使用其他包管理器您必須在 Yarn Berry 項(xiàng)目中處理更多的文件和文件夾。有些是可選的,有些是強(qiáng)制性的。

Yarn Berry 不再支持 .npmrc 或者 .yarnrc;他需要一個 .yarnrc.yml。對于傳統(tǒng)的生成 node_modules 文件夾的工作流程,您必須提供 nodeLinker 配置來使用 node_modules 或者 pnpm 的配置(這塊沒看懂)。

# .yarnrc.yml
nodeLinker: node-modules # or pnpm

運(yùn)行 $ yarn 會將所有依賴項(xiàng)安裝在一個 node_modules 文件夾中。并且生成一個 yarn.lock 文件,該文件較新但與 Yarn Classic 不兼容。此外,還會生成一個用于離線安裝的 .yarn/cache/ 文件夾。該文件夾是可選的,用于存儲項(xiàng)目使用的 Yarn Berry 版本。

.
├── .yarn/
│   ├── cache/
│   └── releases/
│       └── yarn-3.1.1.cjs
├── node_modules/
├── .yarnrc.yml
├── package.json
└── yarn.lock

yarn berry: pnp

無論是對于PnP 的嚴(yán)格模式還是松散模式,跟著 .pnp.cjsyarn.lock 來執(zhí)行 $ yarn 都會生成一個 .yarn/cache/ 還有 .yarn/unplugged。PnP strict 是默認(rèn)模式,如果想要配置 loose 模式,需要如下形式開啟??:

# .yarnrc.yml
nodeLinker: pnp
pnpMode: loose

在 PnP 項(xiàng)目中,除了 releases 文件夾之外,.yarn 文件夾很可能還包含一個提供IDE 支持的 sdk/ 文件夾。根據(jù)您的用例,.yarn 甚至可以包含更多的文件夾。

.
├── .yarn/
│   ├── cache/
│   ├── releases/
│   │   └── yarn-3.1.1.cjs
│   ├── sdk/
│   └── unplugged/
├── .pnp.cjs
├── .pnp.loader.mjs
├── .yarnrc.yml
├── package.json
└── yarn.lock`

pnpm

npmYarn Classic 項(xiàng)目的初始狀態(tài)一樣,pnpm 也需要 package.json 文件。使用 $ pnpm i 安裝依賴項(xiàng)后,會生成一個 node_modules 文件夾,但由于其內(nèi)容是可尋址存儲方式,其結(jié)構(gòu)完全不同。

pnpm 還會生成自己的鎖定文件 pnp-lock.yml。 您可以使用可選文件 .npmrc 提供附加配置。

.
├── node_modules/
│   └── .pnpm/
├── .npmrc
├── package.json
└── pnpm-lock.yml

鎖定文件和依賴存儲


如上一節(jié)所述,每個包管理器都會創(chuàng)建鎖定文件。

lock 文件準(zhǔn)確存儲您的項(xiàng)目安裝的每個依賴項(xiàng)的版本從而實(shí)現(xiàn)更可預(yù)測和確定性的安裝。因?yàn)橐蕾嚢姹竞芸赡苁褂冒姹痉秶暶鳎ɡ纾?v1.2.5)所以這個 lock 文件是很重要的,如果您不“l(fā)ock”您的版本,實(shí)際安裝的版本可能會有所不同。

鎖定文件有時也存儲校驗(yàn)和(我記得是一段hash),我們將在安全部分更深入地介紹。

npm v5+ 開始鎖定文件一直是 npm 主要的功能 ( package-lock.json ) ,pnpm 里是 pnpm-lock.yaml ,在 Yarn Berry 中的 yarn.lock 以新的 YAML 格式出現(xiàn)。

在上一節(jié)中,我們看到了傳統(tǒng)方法,將依賴項(xiàng)安裝在 node_modules 文件夾結(jié)構(gòu)中。這是 npm、Yarn Classic 和 pnpm都使用的方案,(其中 pnpm 比其他方案更有效)。

Yarn Berry 在 PnP 模式下的做法有所不同。依賴項(xiàng)不是 node_modules 文件夾,而是以 zip 文件的形式存儲為 .yarn/cache/.pnp.cjs 文件的組合。

最好將這些鎖定文件置于版本控制之下,因?yàn)槊總€團(tuán)隊(duì)成員都安裝相同的版本,所以它解決了“在你和我的機(jī)器上工作”問題。

CLI


下表比較了 npmYarn Classic、Yarn Berrypnpm 中可用的不同 CLI 命令。這絕不是一個完整的列表,而是一個備忘單。本節(jié)不涉及與workflow 相關(guān)的命令。

npmpnpm 具有許多特別的命令和選項(xiàng)別名,這意味著命令可以有不同的名稱,即$ npm install$ npm add。 此外,許多命令選項(xiàng)都有縮寫版本,例如 -D 來代替 --save-dev。 在表格中,我將所有縮寫版本稱為別名。使用這些包管理器,您都可以增加、更新或刪除多個依賴項(xiàng)。

依賴配置管理

此表涵蓋了用于安裝或更新 package.json 中指定的所有依賴項(xiàng)的依賴項(xiàng)管理命令。

ActionnpmYarn ClassicYarn Berrypnpm
install deps in package.jsonnpm install alias: i, addyarn install or yarnlike Classicpnpm install alias: i
update deps in package.json acc. semvernpm update alias: up, upgradeyarn upgradeyarn semver up (via plugin)pnpm update alias: up
update deps in package.json to latestN/Ayarn upgrade --latestyarn uppnpm update --latest alias: -L
update deps acc. semvernpm update reactyarn upgrade reactyarn semver up reactpnpm up react
update deps to latestnpm update react@latestyarn upgrade react --latestyarn up reactpnpm up -L react
update deps interactivelyN/Ayarn upgrade-interactiveyarn upgrade-interactive (via plugin)$ pnpm up --interactive alias: -i
add runtime depsnpm i reactyarn add reactlike Classicpnpm add react
add dev depsnpm i -D babel alias: --save-devyarn add -D babel alias: --devlike Classicpnpm add -D babel alias: --save-dev
add deps to package.json without semvernpm i -E react alias: --save-exactyarn add -E react alias: --exactlike Classicpnpm add -E react alias: --save-exact
uninstall deps and remove from package.jsonnpm uninstall react alias: remove, rm, r, un, unlinkyarn remove reactlike Classicpnpm remove react alias: rm, un, uninstall
uninstall deps w/o update of package.jsonnpm uninstall --no-saveN/AN/AN/A

安裝配置管理

下面的例子展示了如何在開發(fā)期間管理包。表中使用的術(shù)語:

  • Package: dependency or binary

  • Binary: 一種執(zhí)行工具來自 node_modules/.bin/ 或者 .yarn/cache/ (PnP)

重要的是要理解,Yarn Berry 只允許我們執(zhí)行在 package.json 中或者暴露在 bin/ 文件中的指定的二進(jìn)制文件。

ActionnpmYarn ClassicYarn Berrypnpm
install packages globallynpm i -g ntl alias: --globalyarn global add ntlN/A (global removed)pnpm add --global ntl
update packages globallynpm update -g ntlyarn global upgrade ntlN/Apnpm update --global ntl
remove packages globallynpm uninstall -g ntlyarn global remove ntlN/Apnpm remove --global ntl
run binaries from terminalnpm exec ntlyarn ntlyarn ntlpnpm ntl
run binaries from scriptntlntlntlntl
dynamic package executionnpx ntlN/Ayarn dlx ntlpnpm dlx ntl
add runtime depsnpm i reactyarn add reactlike Classicpnpm add react
add dev depsnpm i -D babel alias: --save-devyarn add -D babel alias: --devlike Classicpnpm add -D babel alias: --save-dev
add deps to package.json without semvernpm i -E react alias: --save-exactyarn add -E react alias: --exactlike Classicpnpm add -E react alias: --save-exact
uninstall deps and remove from package.jsonnpm uninstall react alias: remove, rm, r, un, unlinkyarn remove reactlike Classicpnpm remove react alias: rm, un, uninstall
uninstall deps w/o update of package.jsonnpm uninstall --no-saveN/AN/AN/A

常用命令

該表涵蓋了一些有用的內(nèi)置命令。如果沒有官方的命令,通??梢酝ㄟ^ npm 包或 Yarn Berry 插件來使用第三方命令。

ActionnpmYarn ClassicYarn Berrypnpm
發(fā)包npm publishyarn publishyarn npm publishpnpm publish
list installed depsnpm ls alias: list, la, llyarn list
pnpm list alias: ls
list outdated depsnpm outdatedyarn outdatedyarn upgrade-interactivepnpm outdated
print info about depsnpm explain ntl alias: whyyarn why ntllike Classicpnpm why ntl
init projectnpm init -y npm init (interactive) alias: --yesyarn init -y yarn init (interactive) alias: --yesyarn initpnpm init -y pnpm init (interactive) alias: --yes
print licenses infoN/A (via third-party package)yarn licenses listN/A (or via plugin, other plugin)N/A (via third-party package)
update package manager versionN/A (with third-party tools, e.g., nvm)with npm: yarn policies set-version 1.13.0with Corepack: yarn set version 3.1.1N/A (with npm, Corepack)
perform security auditnpm audityarn audityarn npm auditpnpm audit
add deps to package.json without semvernpm i -E react alias: --save-exactyarn add -E react alias: --exactlike Classicpnpm add -E react alias: --save-exact
uninstall deps and remove from package.jsonnpm uninstall react alias: remove, rm, r, un, unlinkyarn remove reactlike Classicpnpm remove react alias: rm, un, uninstall
uninstall deps w/o update of package.jsonnpm uninstall --no-saveN/AN/AN/A

配置文件


配置包管理器發(fā)生在您的 package.json 和專用的配置文件中。

  • 定義要使用的準(zhǔn)確版本

  • 使用特定的依賴解決策略

  • 配置私有注冊表

  • 告訴包管理器在哪里可以找到 monorepo 中的工作區(qū)

npm

大多數(shù)配置發(fā)生在專用配置文件 .npmrc 中。

如果你想使用 npmworkspaces 功能,你必須在 package.json 中添加workspaces 元數(shù)據(jù)字段來告訴 npm 在哪里可以找到子項(xiàng)目或工作空間的文件夾。

  // ...
  "workspaces": [
    "hooks",
    "utils"
  ]
}

每個包管理器都可以使用公共 npm 注冊表。或許你很可能希望重用它們而不將它們發(fā)布到公共注冊表。您可以在 .npmrc 文件中執(zhí)行此操作配置來私有注冊表。( 現(xiàn)在基本都有私有源了)

# .npmrc
@doppelmutzi:registry=https://gitlab.doppelmutzi.com/api/v4/projects/41/packages/npm/

npm 存在許多配置選項(xiàng),最好在文檔中查看它們。\

yarn

您可以在 package.json 中設(shè)置 yarnworkspaces(必須是私有包)。

{
  // ...
  "private": true,
  "workspaces": ["workspace-a", "workspace-b"]
}

任何可選配置都進(jìn)入一個 .yarnrc 文件。一個常見的配置選項(xiàng)是設(shè)置一個 yarn-path: 它強(qiáng)制每個團(tuán)隊(duì)成員使用指定的二進(jìn)制版本。yarn-path 指向包含特定 Yarn 版本的文件夾(例如 .yarn/releases/)。您可以使用命令來安裝統(tǒng)一的 Yarn Classic 版本(classic.yarnpkg.com/en/docs/cli…)。

yarn berry

Yarn Berry 中配置 workspaces 和在 Yarn Classic 中的配置方式類似(package.json)。 大多數(shù) Yarn Berry 配置發(fā)生在 .yarnrc.yml 中,并且有許多可用的配置選項(xiàng)。

# .yarnrc.yml
yarnPath: .yarn/releases/yarn-3.1.1.cjs

yarn berry可以用 $> yarn plugin import <name> 這種導(dǎo)入方式來擴(kuò)展插件(yarnpkg.com/cli/plugin/…),這個命令也會更新 .yarnrc.yml。

# .yarnrc.yml
plugins:
  - path: .yarn/plugins/@yarnpkg/plugin-semver-up.cjs
    spec: "https://raw.githubusercontent.com/tophat/yarn-plugin-semver-up/master/bundles/%40yarnpkg/plugin-semver-up.js"

如歷史部分所述,因?yàn)榧嫒菪缘年P(guān)系,PnP 嚴(yán)格模式下的依賴關(guān)系可能存在某些問題。此類 PnP 問題有一個典型的解決方案:包擴(kuò)展配置策略。

# .yarnrc.yml
packageExtensions:
  "styled-components@*":
    dependencies:
      react-is: "*"

pnpm

pnpm 使用與 npm 相同的配置機(jī)制,因此您可以使用 .npmrc 文件。配置私有注冊表的工作方式也與使用 npm 相同。借助 pnpm 的工作空間功能可以支持多包項(xiàng)目。要初始化 monorepo,您必須在 pnpm-workspace.yaml 文件中指定包的位置。

# pnpm-workspace.yaml
packages:
  - 'packages/**'

Monorepo


什么是Monorepo

(這里其實(shí)就是三種概念,單倉庫多項(xiàng)目,單倉庫單項(xiàng)目,多倉庫多項(xiàng)目)

monorepo 是一個包含多個項(xiàng)目的存儲庫,這些項(xiàng)目被稱為 workspace 或者包。將所有內(nèi)容保存在一個地方而不是使用多個存儲庫是一種項(xiàng)目組織策略。

當(dāng)然,這會帶來額外的復(fù)雜性。Yarn Classic 是第一個啟用此功能的,但現(xiàn)在每個主要的包管理器都提供了工作區(qū)功能。本節(jié)展示如何使用每個不同的包管理器配置工作區(qū)。

npm

npm 團(tuán)隊(duì)在 v7 中發(fā)布了期待已久的npm 工作區(qū)功能。它包含許多 CLI 命令,可幫助從根包中管理多包項(xiàng)目。大多數(shù)命令可以與 workspace 相關(guān)的選項(xiàng)一起使用以告訴 npm 它是否應(yīng)該針對特定、多個或所有工作空間運(yùn)行。

# Installing all dependencies for all workspaces
$ npm i --workspaces.
# run against one package
$ npm run test --workspace=hooks
# run against multiple packages
$ npm run test --workspace=hooks --workspace=utils
# run against all
$ npm run test --workspaces
# ignore all packages missing test
$ npm run test --workspaces --if-present

tips: 與其他包管理器相比,npm v8 目前不支持高級過濾或并行執(zhí)行多個與工作區(qū)相關(guān)的命令。

yarn

2017 年 8 月,Yarn 團(tuán)隊(duì)宣布在workspace功能方面提供 monorepo 支持。在此之前,只能在Lerna等第三方軟件的多包項(xiàng)目中使用包管理器。Yarn 的這一新增功能也為其他包管理器實(shí)現(xiàn)此類功能鋪平了道路。

如果你有興趣,可以參考如何在有和沒有 Lerna 的情況下使用 Yarn Classic 的工作區(qū)功能。但是這篇文章只會介紹一些必要的命令,以幫助您管理 Yarn Classic 工作區(qū)設(shè)置中的依賴關(guān)系。

# 為所有工作空間安裝所有依賴項(xiàng)
$ yarn 
# 顯示依賴關(guān)系樹
$ yarn workspaces info 
# 再一個包運(yùn)行啟動
$ yarn workspace awesome - package start
  # 將Webpack添加到包
$ yarn workspace awesome - package add - D webpack
  # add React 對所有包
$ yarn add react -W

yarn berry

Yarn Berry 從一開始就以工作區(qū)為特色,因?yàn)樗膶?shí)現(xiàn)是建立在 Yarn Classic 的概念之上的。在Reddit 評論中,Yarn Berry 的主要開發(fā)人員簡要概述了面向工作空間的功能,包括:

  • $ yarn add --interactive: 可以在安裝包時重用來自其他工作區(qū)的版本

  • $ yarn up:更新所有工作區(qū)的包

  • $ yarn workspaces focus:僅為單個工作區(qū)安裝依賴項(xiàng)

  • $ yarn workspaces foreach:在所有工作區(qū)上運(yùn)行命令

Yarn Berry 使用大量可用于 package.json 文件的 dependenciesdevDependencies 字段的協(xié)議。其中就有 workspace協(xié)議。

Yarn Classic 的工作區(qū)相比,Yarn Berry 明確定義依賴項(xiàng)必須是此 monorepo 中的包之一。否則如果版本不匹配,Yarn Berry 可能會嘗試從遠(yuǎn)程注冊表獲取其版本。

{
  // ...
  "dependencies": {
    "@doppelmutzi/hooks": "workspace:*",
    "http-server": "14.0.0",
    // ...
  }  
}

pnpm

通過 workspace 這種協(xié)議,pnpm 促成了類似于 Yarn Berrymonorepo 項(xiàng)目。許多 pnpm 命令接受 --recursive (-r) 或者 --filter 這種在 monorepo 上下文中特別有用的選項(xiàng)。它的原生過濾命令也是對 Lerna 的一個很好的補(bǔ)充。

# prune all workspaces  
pnpm -r exec -- rm -rf node_modules && rm pnpm-lock.yaml  
# run all tests for all workspaces with scope @doppelmutzi
pnpm recursive run test --filter @doppelmutzi/`

性能 & 磁盤效率


性能是選型決策的關(guān)鍵部分。本節(jié)展示了基于一個小型和一個中型項(xiàng)目的基準(zhǔn)測試。以下是有關(guān)示例項(xiàng)目的一些說明:

  • 兩組基準(zhǔn)都不使用工作區(qū)功能

  • 小項(xiàng)目指定33個依賴

  • 中項(xiàng)目指定44個依賴

我用三個用例 (UC) 對我們的每個包管理器變體進(jìn)行了一次測量。要了解詳細(xì)的評估和解釋,請查看項(xiàng)目 1 (P1)和項(xiàng)目 2 (P2)的結(jié)果。

  • UC 1:沒有緩存/存儲,沒有鎖定文件,沒有 node_modules.pnp.cjs

  • UC 2:存在緩存/存儲,沒有鎖定文件,沒有 node_modules.pnp.cjs

  • UC 3:存在緩存/存儲,存在鎖定文件,沒有 node_modules.pnp.cjs

我使用工具gnomon來測量安裝消耗的時間( yarn | gnomon )。此外我測量了生成文件的大小 $ du -sh node_modules。

Performance results for Project 1






Methodnpm v8.1.2Yarn Classic v1.23.0pnpm v6.24.4Yarn Berry PnP loose v3.1.1Yarn Berry PnP strict v3.1.1Yarn Berry node_modules v3.1.1Yarn Berry pnpm v3.1.1
UC 186.63s108.89s43.58s31.77s30.13s56.64s60.91s
UC 241.54s65.49s26.43s12.46s12.66s46.36s40.74s
UC 323.59s40.35s20.32s1.61s1.36s28.72s31.89s
Files and sizepackage-lock.json: 1.3M node_modules: 467Mnode_modules: 397M yarn.lock: 504Kpnpm-lock.yaml: 412K node_modules: 319Myarn.lock: 540K cache: 68M unplugged: 29M .pnp.cjs: 1.6Myarn.lock: 540K cache: 68M unplugged: 29M .pnp.cjs: 1.5Mnode_modules: 395M yarn.lock: 540K cache: 68Mnode_modules: 374M yarn.lock: 540K cache: 68M
Performance results for Project 2






Methodnpm v8.1.2Yarn Classic v1.23.0pnpm v6.24.4Yarn Berry PnP loose v3.1.1Yarn Berry PnP strict v3.1.1Yarn Berry node_modules v3.1.1Yarn Berry pnpm v3.1.1
UC 134.91s43.26s15.6s13.92s6.44s23.62s20.09s
UC 27.92s33.65s8.86s7.09s5.63s15.12s14.93s
UC 35.09s15.64s4.73s0.93s0.79s8.18s6.02s
Files and sizepackage-lock.json: 684K node_modules: 151Myarn.lock: 268K node_modules: 159Mpnpm-lock.yaml: 212K node_modules: 141M.pnp.cjs: 1.1M .pnp.loader.mjs: 8.0K yarn.lock: 292K .yarn: 38M.pnp.cjs: 1.0M .pnp.loader.mjs: 8.0K yarn.lock: 292K .yarn: 38Myarn.lock: 292K node_modules: 164M cache: 34Myarn.lock: 292K node_modules: 156M cache: 34M

安全


npm

npm 在處理壞包時有點(diǎn)過于寬容并且遇到了一些直接影響許多項(xiàng)目的安全漏洞。例如,在 5.7.0 版本中,當(dāng)您在 Linux 操作系統(tǒng)上執(zhí)行 sudo npm 命令時,可以更改系統(tǒng)文件的所有權(quán),從而導(dǎo)致操作系統(tǒng)無法使用。

另一起事件發(fā)生在 2018 年,涉及比特幣被盜。 Node.js 包EventStream在其 3.3.6 版本中添加了惡意依賴項(xiàng)。這個惡意包包含一個加密方法試圖從開發(fā)者的機(jī)器上竊取比特幣。

為了幫助解決這些問題,新的 npm 版本使用密碼算法來檢查您安裝的軟件包的完整性。SHA-512。

yarn

Yarn ClassicYarn Berry 從一開始就使用校驗(yàn)和來檢驗(yàn)每一個包的完整性。Yarn 還試圖阻止您檢索在 package.json 中未聲明的惡意包:如果發(fā)現(xiàn)不匹配,則中止安裝。

PnP 模式下的 Yarn Berry 沒有傳統(tǒng) node_modules 方式的安全問題。與 Yarn Classic 相比,Yarn Berry 提高了命令執(zhí)行的安全性。您只能執(zhí)行已在 package.json 聲明的包。此安全功能類似于 pnpm,我將在下面進(jìn)行描述。

pnpm

pnpm 還是使用校驗(yàn)和來驗(yàn)證每個已安裝包的完整性,然后再執(zhí)行其代碼。

正如我們在上面提到的,npmYarn Classic 都存在由于提升而導(dǎo)致的安全問題。pnpm 避免了這種情況,因?yàn)樗墓芾砟P筒皇褂锰嵘?;相反,它會生成嵌?node_modules 文件夾,從而消除非法依賴訪問的風(fēng)險(xiǎn)。這意味著依賴關(guān)系都在 .package.json 中聲明了。

正如我們所討論的,這在 monorepo 設(shè)置中尤其重要,因?yàn)樘嵘惴ㄓ袝r會導(dǎo)致依賴的不確定性。

感謝各位的閱讀,以上就是“JavaScript包管理器實(shí)例比較分析”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對JavaScript包管理器實(shí)例比較分析這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

網(wǎng)頁題目:JavaScript包管理器實(shí)例比較分析
當(dāng)前URL:http://muchs.cn/article10/ghipdo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制開發(fā)、企業(yè)建站、網(wǎng)站改版網(wǎng)站收錄、網(wǎng)頁設(shè)計(jì)公司、外貿(mào)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營