国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

新一代包管理工具 Pnpm

開發(fā) 開發(fā)工具
在 npm2 發(fā)展階段,安裝依賴是相對比較直接的,它會直接按照配置文件 package.json 中的依賴項去下載相關(guān)依賴包,而依賴包的組織形式則是按照樹形結(jié)構(gòu)去排列的。

背景

如果你從事過前端方面的工作和開發(fā),相信你對 npm 和 yarn 這樣的工具已經(jīng)再熟悉不過了。作為包管理工具,npm 已經(jīng)有了長足的歷史[1]。一個項目初始化過程都需要通過 npm install 命令安裝相關(guān)的依賴到 node_modules 目錄下,對于較大型的前端項目,node_modules 的大小很多時候是超乎我們想象的。而 npm 在版本更新迭代的過程中,也一直在優(yōu)化這個問題,下面我們就簡要聊聊 npm 的發(fā)展歷程。

npm 發(fā)展

npm2

在 npm2 發(fā)展階段,安裝依賴是相對比較直接的,它會直接按照配置文件 package.json 中的依賴項去下載相關(guān)依賴包,而依賴包的組織形式則是按照樹形結(jié)構(gòu)去排列的。由于不同的包的依賴關(guān)系在版本上差異較大,依賴關(guān)系相對復(fù)雜,所以 npm2 直接按照配置去下載并組織依賴的方式,是簡單明晰的做法,保證了各個依賴的獨立性,在依賴變更時,相互并不影響,其關(guān)系可以通過下圖來描述:

從上圖中,我們可以看到

  • A、B、C 包相互獨立
  • A、B、C 包可能會依賴相同的包,比如 D@1.0
  • A、B、C 包可能會存在較深的依賴層級,比如 C package

其中 2 和 3 這兩點的負面影響會隨著項目復(fù)雜度而上升,可能會導(dǎo)致的幾個問題:

  • 較大的冗余。多次下載的相同的依賴包 D@1.0,無法實現(xiàn)共享
  • 較深層級的依賴樹。

Too many dependencies break the Windows file system[2]

Maximum Path Length Limitation[3]

Why does the 260 character path length limit exist in Windows?[4]

node_modules 依賴包路徑過長,超出操作系統(tǒng)最長路徑限制( windows:260 字符,macos:1024 字符),參見:

太深的層級導(dǎo)致文件查找復(fù)雜度上升,嚴重影響性能,增加耗時

Note: 通過 npm ls --depth=n 查看項目相關(guān)依賴層級深度

npm3

為解決 npm2 中存在的冗余和依賴樹問題,npm3 對依賴項進行了依賴扁平化討論和處理[5]

扁平化具體來講就是依賴不在按照樹型進行安裝,而是安裝將依賴安裝在同級目錄下,npm install安裝依賴時,會按照配置文件 package.json 里的依賴順序進行解析,遇到新包就把它放在第一層級的目錄(如 D@1.0、E@1.0、F@1.0),后面如果遇到第一級目錄已有的包,會先進行依賴版本判斷,如果版本一樣則忽略,否則會按照 npm2 的方式依次掛在依賴包目錄下,這樣處理的原理遵循了`Nodejs`的依賴解析規(guī)則[6]:當(dāng)前目錄下沒有找到node_modules,它將遞歸解析父目錄下的node_modules。

使用 npm3 安裝依賴后如下圖:

這種扁平化處理方式一定程度上緩解了冗余和依賴樹問題,同時 npm3 還支持動態(tài)安裝更新包,如果依賴有更新,可以通過 npm dedupe 命令對依賴樹進行優(yōu)化。

但是 npm3 也存在部分問題,比如:

phantom_deps(幻影依賴)[7]。npm3不會以確定的方式安裝依賴項。舉例來說:我們在 NodeJS 中 require() 的函數(shù),不需要考慮配置文件 package.json 中是否有該依賴項。這可能會導(dǎo)致依賴版本不兼容,并且開發(fā)者不容易發(fā)現(xiàn);另外,由于`Nodejs`的依賴解析規(guī)則[8],這還會導(dǎo)致幻影 node_modules ,即依賴向上查找,可能會越過代碼目錄自身的 node_modules 。如下:

- my-monorepo/
- package.json
- node_modules/
- semver/
- ...
- my-monorepo/my-library/
- package.json
- lib/
- index.js
- node_modules/
- brace-expansion
- minimatch
- ...

my-monorepo/my-library/lib/index.js 可能使用的是my-monorepo/node_modules 中的依賴,而非自身目錄 my-monorepo/my-library/node_modules

npm doppelgangers(npm 分身)[9]。簡單來講,npm 分身是指同一個依賴的不同版本會出現(xiàn)在 node_modules 中,比如項目中同時依賴了 A@1.0.0 和 A@2.0.0,無論是扁平化處理A@1.0.0 或 A@2.0.0,另一個依賴還是會被重復(fù),如果這樣的分身較多,就會導(dǎo)致一些潛在問題,比如擴展包大小變大、相關(guān)類型校驗交叉等

npm5

npm5 通過添加 lock 文件來記錄依賴樹信息,進行依賴鎖定,從而唯一確定 node_modules 的結(jié)構(gòu),這樣處理可以保證團隊成員使用同一份node_modules依賴結(jié)構(gòu)。但是,我們前文提到的平鋪式的算法的復(fù)雜性、幻影依賴和分身問題仍然沒有解決。

pnpm 簡介

前文我們大致梳理了 npm 的發(fā)展和遺留問題。而 pnpm 比較巧妙地解決了它們,并且極大地提升了依賴包管理的效率。

pnpm 指 performant npm(高性能的 npm),如 pnpm 官網(wǎng)[10]所言,它是快速的,節(jié)省磁盤空間的包管理工具,同時,它也較好地支持了 workspace 和 monorepos。

pnpm 效果

與 npm、yarn、yarn pnp 工具鏈效果對比,來自 pnpm benchmarks[11]

action

cache

lockfile

node_modules

npm

pnpm

Yarn

Yarn PnP

install




1m 9.5s

15.3s

16.6s

23.6s

install

?

?

?

2.4s

1.3s

2.3s

n/a

install

?

?


14.8s

4s

6.8s

1.5s

install

?



21.8s

8.9s

11.2s

6.2s

install


?


35.4s

13.4s

12s

17.9s

install

?


?

3.1s

1.9s

7s

n/a

install


?

?

2.4s

1.3s

7.6s

n/a

install



?

3s

6.1s

11.8s

n/a

update

n/a

n/a

n/a

2.3s

11.8s

15.5s

28.3s

從上表數(shù)據(jù)我們可以看出,pnpm 的各項性能均比其它包管理工具有優(yōu)勢,那你可能會想,為什么 pnpm 有如此優(yōu)越的表現(xiàn),接下來我們聊聊 pnpm 的主要原理

pnpm 的原理

pnpm 主要有兩個不同與其包管理工具的特性:

基于硬鏈接的 node_modules

pnpm 創(chuàng)建從全局存儲到項目中 node_modules 文件夾的硬鏈接[12],而硬鏈接指向磁盤上原始文件所在的同一位置,具體來說就是 node_modules 中每個包的每個文件都是來自內(nèi)容可尋址存儲[13]的硬鏈接,簡言之,就是特定版本和名稱的包全局只有一份。舉例來看:

node_modules
└── .pnpm
├── bar@1.0.0
│ └── node_modules
│ └── bar -> <store>/bar
│ ├── index.js
│ └── package.json
└── foo@1.0.0
└── node_modules
└── foo -> <store>/foo
├── index.js
└── package.json

node_modules 下面的唯一文件夾叫做 .pnpm, .pnpm 下面是一個 文件夾,而在其下面 的文件夾是一個基于內(nèi)容可尋址存儲的硬鏈接。同時,我們也可以通過 pnpm root 命令來打印當(dāng)前項目中存放模塊(modules)的有效目錄。

基于依賴解析的軟鏈接 symlinks

觀察以下依賴包結(jié)構(gòu):

node_modules
├── foo -> ./.pnpm/foo@1.0.0/node_modules/foo
└── .pnpm
├── bar@1.0.0
│ └── node_modules
│ └── bar -> <store>/bar
└── foo@1.0.0
└── node_modules
├── foo -> <store>/foo
└── bar -> ../../bar@1.0.0/node_modules/bar

我們可以看到在 foo@1.0.0/node_modules/bar 內(nèi)引用了 bar 的軟鏈接 ../../bar@1.0.0/node_modules/bar,而在項目里引用 foo 的軟鏈接 ./.pnpm/foo@1.0.0/node_modules/foo,如果項目內(nèi)新增一個依賴包 qar@2.0.0,則其引用結(jié)構(gòu)如下:

node_modules
├── foo -> ./.pnpm/foo@1.0.0/node_modules/foo
└── .pnpm
├── bar@1.0.0
│ └── node_modules
│ ├── bar -> <store>/bar
│ └── qar -> ../../qar@2.0.0/node_modules/qar
├── foo@1.0.0
│ └── node_modules
│ ├── foo -> <store>/foo
│ ├── bar -> ../../bar@1.0.0/node_modules/bar
│ └── qar -> ../../qar@2.0.0/node_modules/qar
└── qar@2.0.0
└── node_modules
└── qar -> <store>/qar

根據(jù)前文我們介紹到的`Nodejs`的依賴解析規(guī)則[14],foo@1.0.0/node_modules/foo/index.js 中所需的依賴包 bar,實際上使用的是bar@1.0.0/node_modules/bar中的內(nèi)容,因此,只有真正在依賴項中的包才能被訪問到。而對于不同的 peer dependencies 的依賴解析原理,可以參考這里 How peers are resolved[15]

通過基于硬鏈接的node_modules和基于依賴解析的軟鏈接原理,我們了解到,當(dāng)我們在相同操作系統(tǒng)下第二次安裝同一個依賴包時,我們需要做的僅僅是創(chuàng)建一個該依賴包對應(yīng)的硬鏈接,對于同一個依賴包的不同版本,也只有不同的部分會被重新保存起來,而具體有沒有 pnpm 是在哪里判斷的呢?全局的 pnpm 索引文件在 ~/.pnpm-store/v3/files。基于此,使用硬鏈接讓依賴包的安裝速度非常快,同時也去除了冗余,節(jié)省較大磁盤空間。

symlinks 符號連接[16]

pnpm 使用

pnpm 的具體使用這里我們不展開介紹了,可以查看官網(wǎng)使用方法[17]和CLI 命令[18]即可。這里只提幾個有意思的點

CI 集成

在 GitHub Actions 上,你可以像這樣使用 pnpm 安裝和緩存依賴項,配置文件目錄: .github/workflows/NAME.yml。

name: pnpm Example Workflow
on:
push:
jobs:
build:
runs-on: ubuntu-20.04
strategy:
matrix:
node-version: [15]
steps:
- uses: actions/checkout@v2
- uses: pnpm/action-setup@v2.0.1
with:
version: 6.20.3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- name: Install dependencies
run: pnpm install

pnpm 除了在開發(fā)體驗方面的優(yōu)越表現(xiàn),在項目集成方面也毫不遜色,對于較大型項目從 npm 或 yarn到pnpm遷移過程后,也得到了極大的優(yōu)化,結(jié)果如下:


Without cache

With cache

yarn 2 (without dedupe)

6min 31s

1min 11s

yarn 3 (without dedupe)

4min 50s

57s

yarn 3

4min 1s

50s

yarn 3 (optimized)

1min 10

45s

pnpm

58s

24s

通過以上數(shù)據(jù),我們可以 pnpm 在 CI 應(yīng)用中的良好表現(xiàn)。

具體可以參考這篇最佳實踐 A story of how we migrated to pnpm[19]

pnpm 前置

項目中使用 pnpm 時,如果你不希望項目內(nèi)其他人使用 npm i 或 yarn這類包管理器,可以在 package.json 配置文件中添加預(yù)安裝 preinstall 配置項,從而規(guī)范使用統(tǒng)一的包管理器。

{
"scripts": {
"preinstall": "npx only-allow pnpm"
}
}

管理 NodeJS 版本

在以前,如果你同時支撐了多個項目,而且需要在其中切換,你可能需要切換不同的 NodeJS 版本,也許你會用到像 nvm 或 Volta[20] 這樣的 NodeJS 版本管理器,而 pnpm 從 v6.12.0 版本后支持了 pnpm env[21] 命令,你可以使用它來安裝并指定使用哪個版本的 NodeJS ,是不是方便了很多。

monorepo 支持

因為pnpm 對 monorepos 的大力支持,像 Vue、Vite 這些開源項目也轉(zhuǎn)而使用了它。使用pnpm run 結(jié)合 --filter 、 --recursive 和 --parallel 選項,可以指定特定包,并高速執(zhí)行相關(guān)命令。這樣做的好處是之前要另外安裝 lerna 這種 monorepo 管理工具的場景,現(xiàn)在 pnpm 可以包攬了。詳細文章可以參考這里 pnpm vs Lerna: filtering in a multi-package repository[22]。

總結(jié)

本文從 pnpm 的出現(xiàn)背景開始,簡要介紹了 npm 的發(fā)展過程及存在的問題,繼而對 pnpm 及其效果進行了簡介,重點講述了 pnpm 的實現(xiàn)原理,并從應(yīng)用側(cè)選擇了四個點展開。

pnpm 作為新一代包管理器,自身有不少優(yōu)越的表現(xiàn),它通過硬鏈接和軟鏈接的方式,解決了 npm幻影依賴和分身問題,并且較好地解決了依賴包復(fù)用問題,從而實現(xiàn)了依賴包高效快速的安裝。需要特別注意的是 pnpm 嚴格遵循了 Nodejs 依賴解析規(guī)則,規(guī)避了之前任意依賴包的訪問修改問題。

當(dāng)然,pnpm 使用過程中也存在一些問題,包括 Vue 官方在遷移過程中,也處理過部分問題。另外,一些包也存在兼容性問題,由于包自己實現(xiàn)了模塊解析,并沒有遵循相關(guān)規(guī)范。但 pnpm 也提供了相關(guān)解決方法。具體參考 pnpm FAQ[23]。

參考資料:

[1]歷史: https://github.com/npm/cli/blob/latest/changelogs/CHANGELOG-1.md

[2]Too many dependencies break the Windows file system: https://github.com/npm/npm/issues/3697

[3]Maximum Path Length Limitation: https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd

[4]Why does the 260 character path length limit exist in Windows?: https://stackoverflow.com/questions/1880321/why-does-the-260-character-path-length-limit-exist-in-windows

[5]依賴扁平化討論和處理: https://github.com/npm/cli/blob/latest/changelogs/CHANGELOG-3.md

[6]Nodejs的依賴解析規(guī)則: https://nodejs.org/api/modules.html#all-together

[7]phantom_deps(幻影依賴): https://rushjs.io/pages/advanced/phantom_deps/

[8]npm doppelgangers(npm 分身): https://rushjs.io/pages/advanced/npm_doppelgangers/

[9]pnpm 官網(wǎng): https://pnpm.io/

[10]pnpm benchmarks: https://pnpm.io/zh/benchmarks

[11]硬鏈接: https://zh.wikipedia.org/wiki/%E7%A1%AC%E9%93%BE%E6%8E%A5

[12]內(nèi)容可尋址存儲: https://en.wikipedia.org/wiki/Content-addressable_storage

[13]How peers are resolved: https://pnpm.io/zh/how-peers-are-resolved

[14]symlinks 符號連接: https://zh.wikipedia.org/wiki/%E7%AC%A6%E5%8F%B7%E9%93%BE%E6%8E%A5

[15]使用方法: https://pnpm.io/zh/pnpm-cli

[16]CLI 命令: https://pnpm.io/zh/cli/add

[17]A story of how we migrated to pnpm: https://divriots.com/blog/switching-to-pnpm

[18]Volta: https://volta.sh/

[19]pnpm env: https://pnpm.io/zh/cli/env

[20]pnpm vs Lerna: filtering in a multi-package repository: https://medium.com/pnpm/pnpm-vs-lerna-filtering-in-a-multi-package-repository-1f68bc644d6a

[23]pnpm FAQ: https://pnpm.io/faq#pnpm-does-not-work-with-your-project-here

責(zé)任編輯:武曉燕 來源: 青梅主碼
相關(guān)推薦

2022-02-07 23:03:07

Python工具管理庫

2022-08-03 08:02:46

PDM工具Python

2022-06-28 16:30:26

管理工具Python

2022-07-01 09:17:14

Pythonpoetry工具

2022-05-16 09:14:28

前端構(gòu)建工具

2022-05-23 08:59:02

piniavue插件

2025-04-17 03:00:00

dbt數(shù)據(jù)轉(zhuǎn)換工具開源

2012-07-02 10:36:19

菲亞特

2022-03-10 16:01:29

Playwright開源

2025-11-18 09:25:09

2020-10-09 11:50:10

ReactRecoil前端

2020-11-13 15:40:18

React前端Recoil

2013-01-04 16:15:08

微軟ERPDynamics AX

2013-10-21 10:01:04

編碼工具擴展

2023-12-30 16:30:29

開發(fā)者工具Vite

2016-01-26 11:58:12

2010-02-23 17:21:06

Fedora yum

2022-06-15 15:09:48

管理工具

2010-05-05 18:05:00

新一代數(shù)據(jù)中心

2025-02-13 09:37:58

點贊
收藏

51CTO技術(shù)棧公眾號

亚洲成人自拍偷拍| 国内精品400部情侣激情| 中文字幕免费中文| 日韩1区2区3区| 91精品国产综合久久香蕉最新版 | 欧美精品一卡| 日本午夜人人精品| 风间由美中文字幕在线看视频国产欧美| 亚洲精美色品网站| jizzjizz亚洲| 日韩欧美一区二区三区在线| 欧美亚洲日本| 色国产精品一区在线观看| 久草影视在线| 亚洲精品国产品国语在线app| 色悠悠久久综合网| 欧美午夜在线播放| 久久人人爽人人爽爽久久| 国产在线精品一区二区三区》| 91网站在线观看免费| 亚洲1区2区3区4区| 国产美女特级嫩嫩嫩bbb片| 成人在线中文| 日韩中文字幕视频| 国产成人精品一区二区三区在线 | 亚洲五月六月| 免费中文字幕日韩欧美| 精品综合在线| 七七婷婷婷婷精品国产| 国产一区二区三区在线看 | 日韩精品一区二区三区丰满| 欧美成人免费| 久久一区二区三区四区| 国产精品久久久久毛片软件| 日韩精品无码一区二区三区免费| 久久亚洲精品小早川怜子| 99视频在线免费| 亚洲最快最全在线视频| 中文在线一二区| 欧美偷拍一区二区| 波多野结衣中文字幕久久| 亚洲老头同性xxxxx| 久久精品黄色| 久久久久久久久久久网站| 国产一区日韩| 国产亚洲情侣一区二区无| 久久精品国产成人一区二区三区| 国产玉足脚交久久欧美| 亚洲视频一区二区在线| 无人视频在线观看免费| 精品国产免费人成电影在线观看四季 | 亚洲国产欧美在线人成| av网站无病毒在线| 日韩国产精品视频| 国产精品超碰| 97视频中文字幕| 久久99久久99精品免视看婷婷 | 国产一区二区福利| 成人嫩草影院免费观看| 欧美日韩中文字幕| 日韩脚交footjobhd| 久久久久亚洲精品国产| 91av精品| 成年网站在线免费观看| 色久优优欧美色久优优| 国产经典一区| 91久久国产综合久久蜜月精品| 精品午夜久久福利影院| 三上悠亚在线资源| 亚洲国产精品va在线看黑人| 伊人久久大香线蕉综合网蜜芽| 五月天丁香综合久久国产| 日韩理论片网站| heyzo在线播放| 国产成人综合精品在线| 久久99日本精品| 中文字幕在线影视资源| 国产亚洲欧洲高清一区| 女人天堂亚洲aⅴ在线观看| 国产精品12345| 欧美日韩一区二区三区高清 | 日韩精品极品视频| 色婷婷一区二区三区| 国产情侣第一页| 色婷婷亚洲一区二区三区| 欧美性www| 欧美日韩中文国产一区发布| 国产精品国模大尺度视频| 182在线视频观看| 国产精品老女人精品视频 | 日韩电影免费观看高清完整| 国产精品家庭影院| 在线黄色的网站| 成人免费视频视频在| 国产精品久久久久影院老司| 亚洲精品永久免费视频| 国产精品亚洲一区| 夜色激情一区二区| 久久av网站| 特级西西人体www高清大胆| 欧美性色aⅴ视频一区日韩精品| 亚洲超碰在线观看| 国产又粗又长又爽视频| 在线综合视频播放| 亚洲国产精品日韩专区av有中文| 黄色成人免费看| 少妇高潮久久77777| 男人操女人的视频在线观看欧美| 日韩大胆人体| 国产精品免费看久久久香蕉| 国产精品电影一区二区三区| 日本一区影院| 337p粉嫩大胆噜噜噜鲁| 中日韩美女免费视频网址在线观看 | 一本一本久久a久久综合精品| 亚洲熟妇av一区二区三区| 日韩国产中文字幕| 日韩影院免费视频| 欧美成人xxx| 狠狠色综合一区二区| 色av一区二区| 中文字幕亚洲精品乱码| 一不卡在线视频| 国产欧美日韩免费| 亚洲国产精品久久久久秋霞影院| 狂野欧美xxxx韩国少妇| 人妻夜夜添夜夜无码av| 亚洲欧美成人一区二区在线电影| 久久机这里只有精品| av中文资源在线资源免费观看| 欧美日韩在线高清| 欧美精品一区二区三区在线播放| 久久福利精品| 91小视频xxxx网站在线| 欧美一卡2卡3卡4卡无卡免费观看水多多| 在线看一区二区| 国产精品嫩草99av在线| 图片区小说区亚洲| 黄色免费高清视频| 中文字幕最新精品| 91玉足脚交白嫩脚丫在线播放| 青青国产精品| 亚洲欧美自拍另类日韩| 国产91免费看片| 亚洲二区视频在线| 中文字幕av亚洲精品一部二部| 视频免费一区| 亚洲欧美成人一区| 日韩中文字幕视频在线观看| 久久伊99综合婷婷久久伊| 国产精品流白浆在线观看| 91嫩草在线播放| 精品蜜桃一区二区三区| 亚洲精品一二区| 久久网这里都是精品| 九九综合久久| 77777影视视频在线观看| 日韩视频在线观看视频| 久久香蕉国产线看观看av| 亚洲日韩欧美一区二区在线| 国产精品99在线观看| 日本不卡不卡| 日韩 欧美 自拍| 久久久久久高潮国产精品视| 亚洲1区2区3区视频| 日本在线播放一区二区三区| 成人国产激情| 国产经典视频一区| 精品卡一卡二| 北条麻妃在线一区二区| 精品女同一区二区三区在线播放| 青椒成人免费视频| 国产乱人伦精品一区| 嫩草在线播放| 17c丨国产丨精品视频| 国产精品成人免费电影| 日韩三区在线观看| 久久精品亚洲精品国产欧美| 亚洲精品小说| 色猫猫成人app| 超碰在线94| 欧洲金发美女大战黑人| 日本电影亚洲天堂| 精品精品国产高清一毛片一天堂| 中文av一区二区| 日韩综合小视频| 亚洲综合小说图片| 涩涩在线视频| 婷婷亚洲一区二区三区| 久久国产精品网| 97人摸人人澡人人人超一碰| www.xxxx欧美| 欧美精品视频www在线观看| 日本一区二区视频在线| 亚洲免费一区二区| 天堂99x99es久久精品免费| 三级中文字幕在线观看| 头脑特工队2在线播放| 大j8黑人w巨大888a片| 国产美女99p|