<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          JavaScript 包管理器簡史(npm/yarn/pnpm)

          共 9131字,需瀏覽 19分鐘

           ·

          2022-01-16 15:03

          針對現(xiàn)如今比較流行的三個 JavaScript 包管理器:npm、yarn、pnpm,做一次簡短的概述和梳理。JavaScript Package Manager History Timeline

          JS 的包管理器,除了咱們接下來要講的 npm/yarn/pnpm 外,歷史上還有過諸如 bower、jspm 等一些“過時”的包管理器,這里就不再贅述。

          以下順序以編年體的方式進行。

          npm v1/v2

          npm 1.0: Released

          [email protected]

          npm 從最早期到 v7.3.0 之間的博客文章。之后的版本變更可以到 github 對應的版本 Changelog 上查找

          不足

          • 依賴包嵌套的問題,導致 node_modules 體積越來越大

          • 語義話版本帶來的依賴不確定的問題(這時還沒有l(wèi)ockfile/npm-shrinkwrap.json 文件)

          • npm cache 功能不足,無離線模式

          npm v3

          2015 年 6 月 26 日 npm3 發(fā)布,v3.0.0 Changelog

          npm3 完全重寫了 npm 的安裝程序。

          一些大的改變

          • peerDependencies 不再導致隱式安裝任何東西。相反,如果缺少包 peerDependencies,npm 現(xiàn)在會發(fā)出警告。

          • engineStrict

          • npm view

          新特性

          • installpostinstall 生命周期腳本現(xiàn)在僅在安裝了所有具有腳本依賴項的模塊后執(zhí)行

          • npm-shrinkwrap.json確保你在其中指定的模塊完全按照指定的內(nèi)容安裝

          • 扁平化 node_modules

          Yarn v0.x

          2016 年 6 月 18 日,yarn 正式在 github 上提交代碼,初始版本為 0.2.0 ,當時名字叫kpm(fbkpm)。

          2016 年 10 月 11 日正式公開發(fā)行。Facebook 官方在 10 月 11 日發(fā)布的這篇文章(此時 yarn 已經(jīng)穩(wěn)定),介紹了 yarn 出現(xiàn)的緣由和特點:Yarn: A new package manager for JavaScript

          文章開篇就說了,在使用 npm 的過程中,他們遇到了:一致性、安全性、離線安裝和性能方面的問題。

          接著介紹了 JavaScript 包管理在 Facebook 的演變,經(jīng)過一系列對 npm 擴展的嘗試和騷操作,最終 facebook 的工程師們想,是不是搞一個新的包管理器呢?在和社區(qū)的其他工程師的交流中,他們得知,大家面臨很多一樣的問題。于是乎在和 Exponent、Google 和 Tilde 等社區(qū)內(nèi)工程師的合作下,誕生了Yarn。

          Yarn 的特點

          lockfiles(yarn.lock)

          Yarn 通過使用 lockfiles 確定性和可靠的安裝算法解決了這些關(guān)于版本控制和非確定性的問題。這些鎖定文件將已安裝的依賴項鎖定到特定版本,并確保每次安裝都會在所有機器上的 node_modules 中產(chǎn)生完全相同的文件結(jié)構(gòu)。

          安裝過程分為三個步驟:

          • Resolution(解析):Yarn 通過向注冊表發(fā)出請求并遞歸查找每個依賴項來開始解析依賴項。

          • Fetching:接下來,Yarn 在全局緩存目錄中查找所需的包是否已經(jīng)下載。如果沒有,Yarn 會獲取包的 tarball 并將其放在全局緩存中,這樣它就可以脫機工作并且不需要多次下載依賴項。依賴項也可以作為 tarball 放置在源代碼管理中,用于完全離線安裝。

          • Linking:最后,Yarn 通過將全局緩存中所需的所有文件復制到本地 node_modules 目錄中來將所有內(nèi)容鏈接在一起。

          所以通過干凈地拆分以上這些步驟并獲得確定性結(jié)果,Yarn 能夠并行化操作,從而最大限度地提高資源利用率并使安裝過程更快。

          其他特點

          除了使安裝更快、更可靠之外,Yarn 還具有其他功能以進一步簡化依賴項管理工作流程。

          • 與 npm 和 bower 工作流程兼容,并支持混合注冊表。
          • 能夠限制已安裝模塊的許可證以及輸出許可證信息的方法。
          • 公開穩(wěn)定的公共 JS API,并通過構(gòu)建工具將日志抽象化以供使用。
          • 更加可讀性、最小的、漂亮的 CLI 輸出。

          Yarn 要不要支持 symlinks(符號鏈接) 的討論

          2016 年 11 月 10 日,一個大佬開了一個 issue:Looking for brilliant yarn member who has first-hand knowledge of prior issues with symlinking modules。

          問:「聽@thejameskyle 說,在開源之前,Yarn 曾經(jīng)做過 symlinks(符號鏈接)。然而,它破壞了太多的生態(tài)系統(tǒng)而不能被認為是一個有效的選擇。」如果您是 yarn 成員,對實際損壞的內(nèi)容有第一手消息,并且可以從技術(shù)上解釋原因,我懇請您回答這個問題。

          然后@sebmck 回答了他的問題:說 symlinks(符號鏈接),對現(xiàn)有的生態(tài)系統(tǒng)不能很好地兼容。

          總結(jié)了幾點:

          符號鏈接的優(yōu)點:

          • 稍微快一點的包安裝。
          • 更少的磁盤使用

          存在的缺點:

          • 操作系統(tǒng)差異
          • 通過添加多種安裝模式來降低 Yarn 的確定性
          • 文件觀察不兼容
          • 現(xiàn)有工具兼容性差
          • 由循環(huán)引起的遞歸錯誤,等等...

          這個 issue,討論了很長的篇幅,這里就不繼續(xù)了,感興趣的可以去觀摩一下。最后顯然 yarn 的團隊暫時不打算支持使用符號鏈接。

          npm 喊話 Yarn

          yarn 發(fā)布后,npm 官方博客當天(2016 年 10 月 11 日)發(fā)表了一篇Hello, Yarn!

          恭喜了 yarn 的開源。并對 yarn 團隊及 facebook 為社區(qū)及整個 npm 生態(tài)做出的貢獻給予了很高的評價。

          npm v4

          隨后的 2016 年 10 月 21 日 npm 4 發(fā)布,并沒有什么重大的變化。

          做了以下更改:

          • npm search 重寫為流結(jié)果,不再支持排序。
          • npm scripts 不再在運行腳本之前預先添加用于運行 npm 的 node 可執(zhí)行文件的路徑。添加 --scripts-prepend-node-path 選項來配置此行為。
          • npt 已被刪除。
          • prepublish 已被棄用,取而代之的是 prepare。臨時添加了一個 prepublishOnly 腳本,它只會在 npm publish 上運行。
          • 如果 npm outdated 發(fā)現(xiàn)任何過時的包,它會以退出代碼 1 退出。
          • npm tag 已在棄用周期后刪除。使用 npm dist-tag。
          • 不再支持部分 shrinkwraps。除了 devDependencies, npm-shrinkwrap.json 被認為是一個完整的安裝清單。
          • npm 的默認 git 分支不再是 master 分支。從現(xiàn)在開始,我們將使用最新的

          npm v5/v6/v7/v8

          從 v5-v8 無特別突破性的重大變更,所以此段我們放在一起講

          npm v5 于 2017 年 5 月 26 日發(fā)布。npm@5 使 npm 向前邁進了一大步,在幾乎所有常見情況下 顯著提高了其性能,修復了由于架構(gòu)而導致的一系列舊錯誤,代碼更加健壯。并使搭建 monorepos 倉庫更輕松,包的安裝更加一致性及安全(增加了 package-lock.json)。

          簡而言之:

          • 因為有了 package-lock.json,所以保障了安裝包的一致性
          • 性能得到了很大的提升
          • 安裝包目錄現(xiàn)在最終會創(chuàng)建一個符號鏈接,并保存到 package lock
          • 重寫了 Cache。(比較重要的部分,這里就不再贅述,感興趣可移步至 changelog 探究)
          • 重寫后的 Cache 有很強的容錯性并支持并發(fā)訪問
          • 對離線模式及緩存安裝進行了優(yōu)化

          npm v6

          v6.0.0 Changelog

          發(fā)布于 2018 年 5 月 4 日。無重大變更。主要是一些優(yōu)化及 BUG 修復。

          npm v7

          v7.0.0 Changelog

          于 2020 年 10 月 13 日發(fā)布。無重大變更。做了一些優(yōu)化及 BUG 修復。支持workspaces概念,作為 npm cli 的一組功能。

          npm v8

          v8.0.0 Changelog

          2021 年 10 月 7 日發(fā)布了 v8.0.0,此版本的目的是放棄對舊 node 版本的支持和 刪除對 require('npm') 的支持。沒有其他突破性變化。

          BREAKING CHANGES

          刪除對 node 10 和 11 的支持 將 node 12 和 14 中的支持上限提高到 LTS (^12.13.0/^14.15.0) 刪除對 require('npm') 的支持 更新也刪除 node10 支持的子依賴項

          pnpm

          2016 年 10 月 19 日發(fā)布的v0.42.0版本,增加了扁平樹結(jié)構(gòu)的支持。使用 yaml 格式存儲 store 信息。

          pnpm 的優(yōu)勢

          2017 年 3 月 19 日 pnpm 作者發(fā)表了一篇Why should we use pnpm?來闡述了 pnpm 的優(yōu)勢。

          主要是采用硬連接和軟連接的方式,提高了安裝速度、節(jié)約了磁盤空間、避免了“幽靈依賴”。而且 yarn 支持的:安全、離線模式、更快的速度,pnpm 都支持,而且速度還要更快。

          [email protected] 于2017 年 6 月 28 日 發(fā)布

          v1.0.0 Changelog

          pnpm version 1 is out!

          初衷

          節(jié)約磁盤空間并提升安裝速度
          • pnpm 創(chuàng)建從全局存儲到項目下 node_modules 文件夾的硬鏈接,從而提高安裝速度并節(jié)約磁盤空間

          • 解決依賴分身的問題,節(jié)省磁盤空間

          • 創(chuàng)建非扁平化的 node_modules 文件夾

          • 基于符號鏈接的 node_modules 結(jié)構(gòu),解決“幽靈依賴”的問題。(Symbolic link(符號鏈接/軟鏈))

          官網(wǎng)的項目初衷有更詳細的講解

          PNPM 的局限

          • npm-shrinkwrap.jsonpackage-lock.json 被忽略。與 pnpm 不同,npm 可以多次安裝相同的 name@version ,并且具有不同的依賴項組合。npm 的鎖文件旨在反映平鋪的 node_modules 布局,但是,由于 pnpm 無法創(chuàng)建類似的布局,因此它無法遵循 npm 的鎖文件格式。但是,如果您希望將鎖定文件轉(zhuǎn)換為 pnpm 的格式,請看 pnpm import。
          • pnpm 不能發(fā)布帶有 bundledDependencies 的 npm 包。目前,也沒有計劃添加對 bundledDependencies 支持,因為它們在發(fā)布中的工作效率不高,即使在 npm 上也是如此。相反,我們建議您使用一個實際的打包器,例如 webpack、rollup 或 ESBuild。
          • Binstubs(在 node_modules/.bin中的文件)總是 shell 文件,而不是指向 JS 文件的符號鏈接。創(chuàng)建 shell 文件是為了幫助支持插件的 CLI 的程序在特殊的 node_modules 結(jié)構(gòu)中能夠正確地找到它們的插件。這是很少有的問題,如果您希望文件是 JS 文件,請直接引用原始文件,如 #736 所示。
          • Node 的 --preserve-symlinks 標志在使用 pnpm 的項目中執(zhí)行時,無法正常工作。

          版本更迭

          隨著 pnpm 的版本更迭,現(xiàn)在已經(jīng)到了 v6.x 版本。歷代的版本更新,其剛開始的核心思想與初衷并沒有發(fā)生變化。并不斷的進行 bug 的修復、性能的優(yōu)化、新特性/命令的增加以及解決包生態(tài)的兼容性問題。

          Yarn v1.x

          Yarn Workspaces

          workspaces 對 monorepo 倉庫更加友好。它可以讓人們自動聚合來自多個 package.json 文件的所有依賴項,并一次性安裝它們。它還在根目錄使用單個 yarn.lock 文件,將它們?nèi)挎i定。此外,Yarn 將在碰巧相互依賴的所有工作區(qū)之間創(chuàng)建符號鏈接,以便最終在所有項目中始終使用最新的代碼。

          通過防止大型項目的較小部分之間的包重復來實現(xiàn)更快、更輕的安裝。

          同時還提到了 lerna,一個流行的單一存儲庫版本管理工具。

          Auto-merging of lockfiles

          自動合并yarn.lock文件的沖突

          Selective version resolutions

          Yarn 現(xiàn)在允許在項目的 package.json 文件中定義一個 resolutions 字段,該字段指示 Yarn 使用某些子依賴項的特定版本,而不管其依賴項設(shè)置的原始模式如何

          yarn 2.x

          2020 年 1 月 25 日,yarn 2.0.0 發(fā)布,帶來了許多大的變動和特性

          為什么要開發(fā) v2 版本

          • Yarn 的代碼變得越來越難維護和擴展。由于這個技術(shù)原因,Yarn 需要一個更加現(xiàn)代化的代碼架構(gòu)來滿足新需求的開發(fā)。
          • 歡迎社區(qū)開發(fā)者貢獻代碼。采用基于插件(Plugin)的模塊化(Modular)代碼架構(gòu),讓開發(fā)者不用搞懂 Yarn 的核心代碼就可以通過實現(xiàn)插件的方式來為 Yarn 添加新的功能。

          新特性

          由于官方介紹篇幅過長,這里只列出重點,更詳細介紹,移步官方介紹文章

          • 可讀性更高的 CLI 輸出
          • 更好的 workspaces 支持
          • New Command: yarn dlx(與 npx 類似)

          Plug'n'Play/pnp

          重點介紹下Plug'n'Play

          零安裝 (Zero-Installs),更加保證依賴的可靠性。因為不再需要安裝,構(gòu)建速度也得到更大的提升

          node_modules 的問題

          過去的安裝方式很簡單:運行 yarn install Yarn 會生成一個 node_modules 目錄,由于其內(nèi)置的 node 解析算法,Node 可以使用該目錄。在這種情況下,Node 不必首先了解什么是“包”:它只根據(jù)文件進行推理。“這個文件在這里存在嗎?不在的話,讓我們看看父 node_modules。它在這里存在嗎?仍然不在的話,繼續(xù)......”,它一直運行,直到找到正確的。由于以下幾個原因,此過程非常低效:

          node_modules 目錄通常包含大量文件。生成它們通常要耗費 yarn install 所需時間的 70% 以上。即使有預先存在的安裝也不能完全的解決,因為包管理器仍然必須將 node_modules 的內(nèi)容與其應該包含的內(nèi)容進行區(qū)分。

          因為 node_modules 生成是一個 I/O-heavy 操作,包管理器沒有太多余地來優(yōu)化它,而不僅僅是做一個簡單的文件復制——即使它可能使用硬鏈接或?qū)憰r復制,它在進行一堆系統(tǒng)調(diào)用來操作磁盤之前,仍然需要區(qū)分文件系統(tǒng)的當前狀態(tài)。

          因為 Node 沒有包的概念,它也不知道文件是否要被訪問。完全有可能您編寫的代碼一天在開發(fā)環(huán)境中正常,但后來在生產(chǎn)中卻損壞了,因為你忘記在 package.json 中列出你的依賴項之一。

          即使在運行時,Node 解析也必須進行一堆 stat 和 readdir 調(diào)用,以確定從哪里加載每個所需的文件。這是非常浪費的,這也是啟動 Node 應用程序需要花費如此多時間的部分原因。

          最后, node_modules 文件夾的設(shè)計是不切實際的,因為它不允許包管理器正確地刪除重復的包。即使可以使用一些算法來優(yōu)化樹布局(提升),我們?nèi)匀粺o法優(yōu)化某些特定模式 - 不僅導致磁盤使用率高于所需,而且某些包在內(nèi)存中多次實例化。

          解決 node_modules 所存在的問題

          Yarn 已經(jīng)知道關(guān)于你的依賴樹的一切——它甚至為你將它安裝在磁盤上。那么,為什么要由 Node 來查找您的包在哪里呢?相反,包管理器的工作應該是通知解釋器,包在磁盤上的位置并管理包之間甚至包版本之間的任何依賴關(guān)系。這就是創(chuàng)建 Plug'n'Play 的原因。

          在這種安裝模式下(從 Yarn 2.0 開始的默認設(shè)置),Yarn 生成單個 .pnp.cjs 文件,而不是通常包含各種包副本的 node_modules 文件夾。.pnp.cjs 文件包含各種映射:一個將包名稱和版本鏈接到它們在磁盤上的位置,另一個將包名稱和版本鏈接到它們的依賴項列表。有了這些查找表,Yarn 可以立即告訴 Node 在哪里可以找到它需要訪問的任何包,只要它們是依賴樹的一部分,并且只要這個文件在你的環(huán)境中加載。

          這種方法有多種好處:

          安裝現(xiàn)在幾乎是即時的。Yarn 只需要生成一個文本文件(而不是潛在的數(shù)萬個)。主要瓶頸成為項目中依賴項的數(shù)量而不是磁盤性能。

          由于減少了 I/O 操作,安裝更加穩(wěn)定和可靠。尤其是在 Windows 上(批量寫入和刪除文件可能會觸發(fā)與 Windows Defender 和類似工具的各種意外交互),I/O 繁重的 node_modules 操作更容易失敗。

          依賴樹的完美優(yōu)化(又名完美提升)和可預測的包實例化。

          生成的 .pnp.cjs 文件可以作為零安裝工作的一部分提交到您的存儲庫,首先無需運行 yarn install。

          更快的應用程序啟動!Node 解析不必像以前一樣遍歷文件系統(tǒng)層次結(jié)構(gòu)(而且很快就根本不需要這樣做了?。?。

          pnpMode:strict/loose

          pnpMode 為”strict”(解決幽靈依賴的問題),這種情況下所有用到的依賴都必須顯式地聲明在 package.json 中,也就是說如果你的模塊聲明了 webpack 作為依賴,webpack 中聲明了 acorn 作為依賴,在”strict”模式下你的模塊不能直接引入 acron,否則會報錯。而”loose”模式下是允許的,但卻不是推薦用法。

          nodeLinker: pnp/node-modules

          nodeLinker 設(shè)置為”node-modules”就和 Yarn 1 和 npm 的方式安裝依賴沒什么區(qū)別了,所有依賴仍然存在于 node_moduels 目錄下,這些情況下也不會生成.pnp.js 文件,因為不需要從 zip 包中解析依賴了。

          兼容性

          請注意,相關(guān)的 CLI 工具,需要兼容 pnp 模式,因為前端庫(例如 react、vue、lodash 等)不會重新實現(xiàn) Node 解析,因此不需要任何特殊邏輯來利用 pnp。

          諸如 Babel、webpack4.x、ESlint、VScode 等需要用到 node 解析的工具或者編輯器,需要結(jié)合相關(guān) pnp 生態(tài)的插件才能正常工作。

          無疑Plug'n'Play是 v2 最重大的一個新特性。當然新的架構(gòu)對開源社區(qū)更加友好,勢必讓 yarn 在往后的發(fā)展更加迅猛。

          Yarn v3

          2021 年 8 月 6 日 Yarn v3 發(fā)布,老規(guī)矩——官方發(fā)了一篇文章來介紹它。

          重大更改主要是對一些小細節(jié)的優(yōu)化

          • 不再支持 Node 10
          • Plug'n'Play hooks 是 .pnp.cjs (vs .pnp.js)
          • 虛擬文件夾現(xiàn)在是 virtual (vs $$virtual)
          • editor SDKs 移至 @yarnpkg/sdks
          • 支持 node 的exports字段

          性能

          經(jīng)過了各種調(diào)整以后,解決了 Yarn 中一些大的資源消耗的問題。安裝速度得到了改進(在某些情況下 比 pnpm 更快)。而且腳本的執(zhí)行往往具有自然開銷,由于 2.4 及更早版本中存在錯誤,導致隨著項目的增加開銷逐漸增加。已經(jīng)解決了這種情況,現(xiàn)在開銷應該是恒定的。

          New node_modules linkers(新的node_modules鏈接器)

          Yarn 是圍繞幾個接口構(gòu)建的。其中之一稱為“鏈接器”,它告訴 Yarn 如何在磁盤上安裝軟件包。這就是我們?nèi)绾巫龅皆诓桓奶啻a的情況下支持 PnP 和 node_modules 安裝的原因。

          這種架構(gòu)的一個優(yōu)點是它允許我們?nèi)绾斡行У氐娲惭b策略。對于此版本,larixer 實現(xiàn)了一個新的實驗性 nmMode 設(shè)置,可用于指示鏈接器使用特定的復制方案:

          • hardlinks-local:當在同一個項目中多次發(fā)現(xiàn)使用同一個包時,將使用硬鏈接(但前提是它們具有完全相同的版本)。
          • hardlinks-global:將在相同的文件上使用硬鏈接(甚至跨不同版本?。?,但也會使它們指向全局內(nèi)容可尋址目錄。這類似于 pnpm 所做的。請注意,如果緩存損壞(例如因為您手動編輯它),Yarn 將在后續(xù)安裝時自動修復它。

          我自己一直在嘗試 pnpm 風格的鏈接器。它尚未發(fā)布,因為可能會導致維護起來的復雜性增加,所以持謹慎態(tài)度。(v3.1.0 中已支持 pnpm 風格的鏈接器)

          其他改進

          • 改進腳本的 shell 支持
          • ESBuild 支持

          我們現(xiàn)在使用 ESBuild 來生成 Yarn 包,并因此努力確保與 Plug'n'Play 安裝的良好兼容性。增加新的@yarnpkg/esbuild-plugin-pnp包。速度提升 6 倍

          • 將命令行框架升級到 Clipanion 3

          即將到來的

          • 核心包(corepack)集成
          • PnP 模式下的 ESM 支持
          • 內(nèi)置 CLI 完成
          • 變更日志生成
          • 改進性能
          • pnpm 風格的鏈接器,等等

          結(jié)語

          對于這三個包管理器的簡單梳理告一段落??v觀發(fā)展,大家都是在互相學習和優(yōu)化,為 JavaScript 社區(qū)的發(fā)展注入了活力,感謝開源精神。

          npm 作為 node 老師的親傳弟子,隨總有人詬病,但影響力依然不減。對于后起之秀的新特性,為保住江湖地位,也不得不跟上小老弟們的步伐。

          Yarn 就像一個學貫中西的絕頂高手,在精研 npm 的傳統(tǒng)招式的同時,又自研獨門絕技,同時又吸收新時代新理念?!叭家钡募軇?,咄咄逼人。

          pnpm 一招硬連接、軟連接獨步天下。比 Yarn 還快的速度,給足了壓力。敢于開拓的年輕人,未來可期。

          JavaScript 包管理器們的故事還在繼續(xù)!

          本文轉(zhuǎn)自:https://zhuanlan.zhihu.com/p/451025256 作者:reahink


          請你喝杯?? 記得三連哦~

          1.閱讀完記得給?? 醬點個贊哦,有?? 有動力

          2.關(guān)注公眾號前端那些趣事,陪你聊聊前端的趣事

          3.文章收錄在Github?frontendThings?感謝Star?

          瀏覽 78
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  永久免费的黄色电影 | 九九成人在线 | 色五月婷婷综合网 | 大香蕉人妻视频 | 美女91影院 |