npm, yarn, pnpm之間的區別

在這里插入圖片描述

前言

在現代化的開發中,一個人可能同時開發多個項目,安裝的項目越來越多,所隨之安裝的依賴包也越來越臃腫,而且有時候所安裝的速度也很慢,甚至會安裝失敗。

因此我們就需要去了解一下,我們的包管理器,在前端比較主流的包管理器主要有三個(當然還有其他優秀的包管理器,本文主要介紹這三個),分別是:npm,yarn,pnpm

幽靈嵌套(Phantom Dependency)

在了解包管理器之前,我們先了解一下包管理的一個難題:幽靈嵌套

幽靈嵌套問題通常發生在依賴之間存在復雜的版本要求時,比如:

  • 包 A 依賴于包 B@1.0.0
  • 包 B 依賴于包 C@2.0.0
  • 另一個包 D 也依賴于 C@3.0.0

在傳統的依賴管理中,可能會導致包 C 的不同版本被嵌套在不同的子依賴樹中,從而在 node_modules 中形成不同路徑的多層嵌套,導致路徑非常深。這種情況一旦發生,如果包 A 和包 D 不同意版本要求,可能會導致不同版本的包 C 被分別安裝在不同的路徑下,出現路徑沖突甚至依賴問題,這就是“幽靈嵌套”現象。

NPM (Node Package Manager)

概述:

npm 是 Node.js 默認的包管理工具,最早由 Node 社區開發并捆綁到 Node.js 中,因此使用最為廣泛。

從npm v2 到npm v7+的升級過程中,從最初使用遞歸的方法處理依賴,造成高度嵌套的依賴樹,到后來使用扁平化管理,一定程度上解決了依賴嵌套問題,但是出現了算法時間過長的問題,最后引入了package-lock.json機制,作用是鎖定依賴結構,一定程度上保持了依賴的穩定性

核心:

  • 采用扁平化依賴管理管理方式
  • 每個依賴包都會在 node_modules 中單獨安裝
  • 相同的依賴可能會被重復安裝多次

特點:

  • 優點:
  1. Node.js 默認包管理器,使用最廣泛,擁有強大的額社區支持
  2. 最早的包管理器,簡單易上手,對初學者友好
  3. package-lock.json 保證依賴版本一致性
  • 缺點:
  1. 安裝速度較慢,占用空間大

目錄結構:

  • npm v2及以前
  1. 依賴樹可能非常深
  2. 相同包會重復安裝
  3. 占用大量磁盤空間
  4. 文件路徑可能超過 Windows 限制
node_modules
├── A
│   └── node_modules
│       └── B
│           └── node_modules
│               └── C
└── D└── node_modules└── B└── node_modules└── C
  • npm v3-6,扁平化管理
  1. 采用扁平化優先的安裝策略
  2. 相同版本的包會被提升到頂層
  3. 不同版本保留在各自的 node_modules 中
  4. 安裝算法比較復雜,需要計算依賴樹
// 假設依賴關系:
// package-A 依賴 lodash@4.0.0
// package-B 依賴 lodash@4.0.0node_modules
├── package-A
├── package-B
└── lodash     // 被提升到頂層

當有版本沖突時:

// package-A 依賴 lodash@4.0.0
// package-B 依賴 lodash@3.0.0node_modules
├── package-A
├── package-B
│   └── node_modules
│       └── lodash  // 3.0.0 版本
└── lodash         // 4.0.0 版本提升到頂層
  • npm v7+, 改進了扁平化管理,引入peer dependencies 處理
  1. 自動安裝 peer dependencies
  2. 更嚴格的版本鎖定
  3. 改進了依賴解析算法
  4. workspaces 支持
node_modules
├── package-A
├── package-B
├── lodash        // 主版本
└── .package-lock.json  // 更嚴格的版本鎖定

Yarn

概述:

Yarn 是一個 JavaScript 包管理工具,最早由 Facebook 推出,主要用于管理項目中的依賴包。和 npm 類似,yarn 解決了在 JavaScript 項目中下載、安裝和管理依賴的需求,并在一定程度上改進了 npm 的一些缺點,比如性能、穩定性和安全性。

核心:

  1. 并行下載提升安裝速度:

傳統的 npm 安裝方式是依次下載依賴,而 Yarn 可以同時下載多個依賴,稱為“并行下載”。這種方式充分利用了網絡帶寬,顯著減少安裝依賴所需的時間,使得安裝速度更快。并行下載尤其在大型項目中效果顯著,能夠有效降低整體安裝時間。

  1. 緩存機制減少重復下載:

Yarn 內置了緩存機制,在首次安裝依賴時會將其緩存到本地。之后再次安裝這些依賴時,如果依賴版本沒有改變,Yarn 會直接從本地緩存中讀取,而不是重新下載。這樣不僅節省了網絡請求,還提升了安裝速度,特別適合離線開發和持續集成場景。

  1. yarn.lock 確保依賴版本一致性:

Yarn 使用 yarn.lock 文件記錄每個依賴的具體版本和來源,確保團隊所有成員在不同機器上安裝時得到的依賴版本完全一致。這避免了“依賴地獄”問題,即由于版本不一致導致的錯誤或不兼容情況,從而提高了開發過程的穩定性。

  1. 更安全的依賴解析機制:

Yarn 在安裝依賴時會校驗每個包的完整性(如 SHA 校驗),以確保包的內容沒有被篡改。這種安全機制能在下載依賴時檢測到潛在的包篡改或惡意代碼的引入,增強了項目的安全性。相比于早期的 npm,Yarn 的這種依賴解析機制更加嚴謹。

  1. Workspace 支持更好的 monorepo 管理:

Yarn 支持 Workspace 功能,允許在單個代碼庫(monorepo)中管理多個項目或包。這種管理方式可以將多個子項目的依賴集中管理、共享,減少重復依賴的安裝。此外,Yarn 還能通過 Workspace 在多個包之間建立相互依賴關系,使 monorepo 項目的開發、構建和測試更加高效。

  1. PnP(Plug’n’Play)模式提供更快的模塊加載:

Yarn 2.x 引入了 PnP 模式,這種模式完全去除了 node_modules 目錄,通過在 .pnp.cjs 文件中記錄依賴映射關系。PnP 不僅減少了磁盤空間的占用,還提升了依賴的加載速度,因為 Node.js 不再需要遞歸遍歷 node_modules。這樣可以加快應用的啟動速度,同時在依賴數量龐大的項目中減少文件系統的壓力。

特點:

  • 優點:
  1. 采用扁平化優先 + 符號鏈接(符號鏈接是一個特殊的文件,它包含對另一個文件或目錄的引用路徑)的組合策略
  2. 相同版本的包會被提升并復用
  3. 不同版本通過符號鏈接保持正確的引用關系
  • 缺點:
  1. 仍然存在幽靈依賴問題
    盡管 Yarn 已經在扁平化和依賴管理上做了優化,但在一些復雜的項目中仍然會出現幽靈依賴問題。所謂幽靈依賴,指的是某個包在項目中使用但并未在 package.json 中聲明,可能是通過其他依賴的間接依賴引入。這種隱式依賴會導致項目依賴關系難以維護,如果間接依賴被移除,可能會導致項目出錯。

  2. 某些場景下的依賴解析較慢
    Yarn 的依賴解析雖然比傳統 npm 更快,但在依賴結構復雜、依賴版本沖突較多的情況下,解析和處理依賴關系可能會變慢。尤其在 monorepo 中,Yarn 需要處理多個包之間的依賴關系,可能出現解析速度不如 pnpm 的情況。

目錄結構:

  • 基本結構
node_modules/
├── package-A/                # 實際文件
├── package-B/                # 實際文件
├── lodash/                   # 提升到頂層的共享包
└── .bin/                     # 可執行文件的符號鏈接
  • 依賴共享案例
// 假設有以下依賴關系:
項目
├── package-A (依賴 lodash@4.0.0)
└── package-B (依賴 lodash@4.0.0)// Yarn 會創建這樣的結構:
node_modules/
├── package-A/
│   └── node_modules/
│       └── lodash -> ../../../lodash  # 符號鏈接
├── package-B/
│   └── node_modules/
│       └── lodash -> ../../../lodash  # 符號鏈接
└── lodash/                            # 實際文件
  • 版本沖突處理
// 當存在版本沖突時:
項目
├── package-A (依賴 lodash@4.0.0)
└── package-B (依賴 lodash@3.0.0)// Yarn 會這樣處理:
node_modules/
├── package-A/
│   └── node_modules/
│       └── lodash -> ../../../lodash    # 指向4.0.0
├── package-B/
│   └── node_modules/
│       └── lodash/                      # 本地安裝3.0.0
└── lodash/                              # 4.0.0版本在頂層

PNPM(Performant NPM)

概述:

pnpm 是一個更現代化的包管理工具,旨在解決 npm 和 yarn 的一些效率和資源管理問題。

  • 核心:
  1. 采用內容尋址存儲系統:

pnpm 使用內容尋址(content-addressable storage)來存儲依賴包。每個依賴包都會被哈希處理,并根據其內容生成唯一的存儲地址。這樣,即使多個項目依賴于相同版本的包,pnpm 也只需要存儲一份,不會重復存儲同樣內容的文件。

  1. 使用硬鏈接和符號鏈接共享依賴:

pnpm 通過在 node_modules 中創建硬鏈接或符號鏈接(symlink),指向內容尋址存儲中實際的依賴包。這樣每個項目可以“共享”依賴,而不必為每個項目單獨存儲依賴包內容。

  • 硬鏈接(Hard Link) :將文件內容鏈接到項目文件夾下,不占用額外磁盤空間。
  • 符號鏈接(Symlink) :為特定版本的包創建路徑映射,使項目代碼能夠準確找到每個依賴包版本的地址。

特點:

  • 優點:
  1. 顯著節省磁盤空間
  2. 安裝速度快
  3. 更嚴格的依賴管理
  4. pnpm-lock.yaml 確保依賴版本一致
  • 缺點:
  1. 不兼容一些使用傳統 node_modules 結構的工具和插件:

  2. 在 pnpm 中,每個依賴都有自己的隔離路徑,某些工具、插件或構建系統可能會假設 node_modules 目錄是扁平的,這可能導致兼容性問題。

  3. 與本地開發和測試環境的潛在不兼容:

  4. 有些項目依賴于本地 node_modules 結構,或者需要直接訪問 node_modules 中的文件。在 pnpm 使用內容尋址和符號鏈接時,這可能會導致某些工具無法正常運行。

目錄結構

  • 內容尋址存儲
.pnpm-store/
└── v3/└── files/├── 00/                              # 前兩位哈希值作為目錄名│   └── deadbeef...                  # 包內容的哈希值└── ff/└── cafebabe...                  # 另一個包的哈希值
  • 依賴結構
node_modules/
├── .pnpm/
│   ├── react@17.0.2/
│   │   └── node_modules/
│   │       ├── react/                       # 實際文件(硬鏈接到 store)
│   │       └── loose-envify/                # react 的依賴
│   └── lodash@4.17.21/
│       └── node_modules/
│           └── lodash/                      # 實際文件(硬鏈接到 store)
├── react -> .pnpm/react@17.0.2/node_modules/react                 # 符號鏈接
└── lodash -> .pnpm/lodash@4.17.21/node_modules/lodash             # 符號鏈接

目錄說明

  • .pnpm/ 文件夾:存放項目的所有依賴包,按 包名@版本號 命名,并在其 node_modules 文件夾中包含該包的實際文件和依賴項。

  • 硬鏈接:.pnpm 中的實際文件并不是直接復制到每個項目中,而是通過硬鏈接指向 pnpm 的全局緩存存儲目錄 (pnpm store)。這樣,不同項目間的相同版本依賴不需要重復下載。

  • 符號鏈接:pnpm 會在項目的 node_modules 根目錄創建符號鏈接,將每個包鏈接到 .pnpm 中實際的包路徑。例如:

  • node_modules/react 是一個符號鏈接,指向 .pnpm/react@17.0.2/node_modules/react
    node_modules/lodash 符號鏈接指向 .pnpm/lodash@4.17.21/node_modules/lodash

工作原理

  • 包安裝:pnpm 會將依賴包下載到全局緩存 (pnpm store) 中,并將實際文件硬鏈接到 .pnpm 文件夾中的特定版本目錄下。
  • 創建符號鏈接:在項目的 node_modules 文件夾內創建符號鏈接,將包名稱指向 .pnpm 中的對應路徑。
  • 引用:項目中的 require(‘react’) 會自動找到 node_modules/react 符號鏈接,并通過符號鏈接訪問實際文件。

總結:

三者同異:

在這里插入圖片描述

使用選擇:

基于這些特點:

  • 如果項目體積較小,團隊成員 Node.js 經驗不同,推薦使用 npm
  • 如果需要更好的性能和可靠性,推薦使用 yarn
  • 如果需要最嚴格的依賴管理、最小的磁盤空間占用,推薦使用 pnpm

常用命令:

npm、yarn 和 pnpm 的常用命令對比表:
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/62171.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/62171.shtml
英文地址,請注明出處:http://en.pswp.cn/web/62171.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

工業檢測基礎-工業相機選型及應用場景

以下是一些常見的工業檢測相機種類、檢測原理、應用場景及選型依據: 2D相機 檢測原理:基于二維圖像捕獲,通過分析圖像的明暗、紋理、顏色等信息來檢測物體的特征和缺陷.應用場景:廣泛應用于平面工件的外觀檢測,如檢測…

C語言連接數據庫

文章目錄 一、初始化數據庫二、創建數據庫連接三、執行增刪改查語句1、增刪改2、查 四、執行增刪改查語句 接下來我簡單的介紹一下怎么用C語言連接數據庫。 初始化數據庫創建數據庫連接執行增刪改查語句關閉數據庫連接 一、初始化數據庫 // 數據庫初始化 MYSQL mysql; MYSQL* r…

優化LabVIEW數據運算效率的方法

在LabVIEW中進行大量數據運算時,提升計算效率并減少時間占用是開發過程中常遇到的挑戰。為此,可以從多個角度著手優化,包括合理選擇數據結構與算法、并行處理、多線程技術、硬件加速、內存管理和界面優化等。通過采用這些策略,可以…

開源模型應用落地-安全合規篇-用戶輸入價值觀判斷(四)

一、前言 在深度合規功能中,對用戶輸入內容的價值觀判斷具有重要意義。這一功能不僅僅是對信息合法性和合規性的簡單審核,更是對信息背后隱含的倫理道德和社會責任的深刻洞察。通過對價值觀的判斷,系統能夠識別可能引發不當影響或沖突的內容,從而為用戶提供更安全、更和諧的…

計算機的錯誤計算(一百七十六)

摘要 利用某一大語言模型計算 的值,輸出為 0 . 例1. 在某一大語言模型下,計算 的值。其中sin中值取弧度。結果保留16位有效數字。 直接貼圖吧: 點評: (1)以上為一個大模型給的答案。從其回答可知&…

數據結構與算法——1204—遞歸分治法

1、斐波那契數列優化 使用滾動變量&#xff0c;保存當前計算結果和前兩項值 (1)RAB (2)更新計算對象&#xff0c;AB&#xff0c;BR #include<iostream> using namespace std;int fun(int n) {if (n 0)return 0;if (n 1 || n 2)return 1;int num11;int num21;int su…

openstack內部rpc消息通信源碼分析

我們知道openstack內部消息隊列基于AMQP協議&#xff0c;默認使用的rabbitmq 消息隊列。談到rabbitmq&#xff0c;大家或許并不陌生&#xff0c;但或許會對oslo message有些陌生。openstack內部并不是直接使用rabbitmq&#xff0c;而是使用了oslo.message 。oslo.message 后端的…

Python 3 和 MongoDB 的集成使用

Python 3 和 MongoDB 的集成使用 MongoDB 是一個流行的 NoSQL 數據庫&#xff0c;以其靈活的數據模型和強大的查詢功能而聞名。Python 3 作為一種廣泛使用的編程語言&#xff0c;與 MongoDB 的集成變得日益重要。本文將介紹如何在 Python 3 環境中集成和使用 MongoDB&#xff…

Postman自定義腳本Pre-request-script以及Test

這兩個都是我們進行自定義script腳本的地方&#xff0c;分別是在請求執行的前后運行。 我們舉兩個可能經常運用到的場景。 (一)請求A先執行&#xff0c;請求B使用請求A響應結果作為參數。如果我們不用自定義腳本&#xff0c;可能得先執行請求A&#xff0c;然后手動復制響應結果…

構建高效OTA旅游平臺的技術指南

1. 引言 在信息技術高速發展的今天&#xff0c;互聯網深刻地改變了人們的旅行方式。傳統的旅行社模式逐漸被在線旅游平臺所取代&#xff0c;OTA&#xff08;Online Travel Agency&#xff0c;在線旅行社&#xff09;旅游平臺應運而生&#xff0c;成為人們獲取旅游信息、預訂旅…

總結的一些MySql面試題

目錄 一&#xff1a;基礎篇 二&#xff1a;索引原理和SQL優化 三&#xff1a;事務原理 四&#xff1a;緩存策略 一&#xff1a;基礎篇 1&#xff1a;定義&#xff1a;按照數據結構來組織、存儲和管理數據的倉庫&#xff1b;是一個長期存儲在計算機內的、有組織的、可共享 的…

116. UE5 GAS RPG 實現擊殺掉落戰利品功能

這一篇&#xff0c;我們實現敵人被擊敗后&#xff0c;掉落戰利品的功能。首先&#xff0c;我們將創建一個新的結構體&#xff0c;用于定義掉落體的內容&#xff0c;方便我們設置掉落物。然后&#xff0c;我們實現敵人死亡時的掉落函數&#xff0c;并在藍圖里實現對應的邏輯&…

Excel技巧:如何批量調整excel表格中的圖片?

插入到excel表格中的圖片大小不一&#xff0c;如何做到每張圖片都完美的與單元格大小相同&#xff1f;并且能夠根據單元格來改變大小&#xff1f;今天分享&#xff0c;excel表格里的圖片如何批量調整大小。 方法如下&#xff1a; 點擊表格中的一個圖片&#xff0c;然后按住Ct…

智能合約

06-智能合約 0 啥是智能合約&#xff1f; 定義 智能合約&#xff0c;又稱加密合約&#xff0c;在一定條件下可直接控制數字貨幣或資產在各方之間轉移的一種計算機程序。 角色 區塊鏈網絡可視為一個分布式存儲服務&#xff0c;因為它存儲了所有交易和智能合約的狀態 智能合約還…

智慧油客:從初識、再識OceanBase,到全棧上線

今天&#xff0c;我們邀請了智慧油客的研發總監黃普友&#xff0c;為我們講述智慧油客與 OceanBase 初識、熟悉和結緣的故事。 智慧油客自2016年誕生以來&#xff0c;秉持新零售的思維&#xff0c;成功從過去二十年間以“以銷售產品為中心”的傳統思維模式&#xff0c;轉向“以…

【深度學習】手機SIM卡托缺陷檢測【附鏈接】

一、手機SIM卡托用途 SIM卡托是用于固定和保護SIM卡的部件&#xff0c;通過連接SIM卡與手機主板的方式&#xff0c;允許設備訪問移動網絡&#xff0c;用戶可以通過SIM卡進行通話、發送短信和使用數據服務。 二、手機SIM卡托不良影響 SIM卡接觸不良&#xff0c;造成信號中斷&…

高新技術企業復審需要哪些材料?

高新技術企業復審需要準備以下材料&#xff1a; 《高新技術企業認定復審申請書》&#xff1b;高新技術企業證書&#xff1b;企業營業執照副本、稅務登記證書&#xff08;復印件&#xff09;&#xff1b;企業職工人數、學歷結構以及研發人員占企業職工的比例證明&#xff1b;五…

消防物證管理系統|DW-S404實現消防物證智能化管理

一、系統概述 智慧消防物證管理系統DW-S404系統旨在借助現代信息技術&#xff0c;達成消防物證管理的高效化、安全化及智能化管理目標。該系統運用物聯網、大數據、云計算等先進技術&#xff0c;實現對消防物證從產生到銷毀的全生命周期跟蹤與監控&#xff0c;從而增強物證管理…

Odoo :一款免費且開源的食品生鮮領域ERP管理系統

文 / 貝思納斯 Odoo金牌合作伙伴 引言 提供業財人資稅的精益化管理&#xff0c;實現研產供銷的融通、食品安全的追蹤與溯源&#xff0c;達成渠道的扁平化以及直面消費者的 D2C 等數字化解決方案&#xff0c;以此提升運營效率與核心競爭力&#xff0c;支撐高質量的變速擴張。…

如何部署vue項目到Github Pages

1.創建vue項目 npm create vitelatest my-vue-app -- --template vue 2.創建github倉庫 3.連接倉庫 在項目根目錄右鍵選擇open git base here&#xff0c;如果沒有安裝git請先安裝git。 初始化倉庫 $ git init $ git add . $ git commit -m "init"將項目與倉庫連…