<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>

          為什么 vue 源碼以及生態(tài)倉庫要遷移 pnpm?

          共 7024字,需瀏覽 15分鐘

           ·

          2022-01-10 14:53

          前言

          隨著前段時(shí)間尤大在 vue3 以及 vite 倉庫中切換包管理為 pnpm 的 pr 成功 merge,以及 vue 生態(tài)中的一些項(xiàng)目例如 VueUse 也切換使用 pnpm,宣告著 vue 生態(tài)中項(xiàng)目倉庫完成了從原有的?yarn workspace monorepo?到?pnpm workspace monorepo?的遷移。

          可以看到 vite 核心貢獻(xiàn)者以及 vue 團(tuán)隊(duì)成員之一的 patak (https://github.com/patak-js) 在 twitter 上對這次項(xiàng)目遷移的生動描述:“項(xiàng)目如同多米諾骨牌一樣倒向了 pnpm”。

          具體關(guān)于 pnpm 相關(guān)介紹可以參考筆者之前寫的一篇文章:?pnpm: 最先進(jìn)的包管理工具?,本文中不會對此做更多的介紹。

          vue 遷移項(xiàng)目

          其中關(guān)于 vue 生態(tài)中項(xiàng)目遷移的具體過程可以參考這些的一些 pr:

          • https://github.com/vuejs/vue-next/pull/4766

          • https://github.com/vitejs/vite/pull/5060

          • https://github.com/vueuse/vueuse/commit/826351ba1d9c514e34426c85f3d69fb9875c7dd9

          其中包括目前 vue3.0 項(xiàng)目源碼倉庫:

          以及目前社區(qū)里面火熱的 bundleless 工具 vite 源碼倉庫:

          可以看到這兩個(gè)的遷移 pr 都是由尤大親手完成改造,同時(shí) pnpm 作者的本人 zkochan(github:?https://github.com/zkochan) 也親自幫 vite 遷移的 pr 做了?code review

          以上幾個(gè)項(xiàng)目都是基于 monorepo 來做的倉庫管理,pnpm 的 workspace 在 monorepo 場景下是有著極好的支持,當(dāng)然也有非 monorepo 項(xiàng)目的遷移,例如由筆者遷移的?naive-ui?倉庫的項(xiàng)目中包管理工具為 pnpm 用于提升 CI 下依賴安裝速度的提升(參考pr: https://github.com/TuSimple/naive-ui/pull/1425 )。

          下面來介紹一些這次的遷移動機(jī)以及引發(fā)問題的源頭,注意以下的內(nèi)容都是根據(jù)一些社區(qū)討論進(jìn)行推斷的,可能并不完整或者準(zhǔn)確,但是對于具體的細(xì)節(jié)我會盡量還原到位,同時(shí)也不會對此過度解讀,希望讀者自行甄別。如果錯(cuò)誤,歡迎指正。

          遷移原因

          在尤大9月份的一條 twitter 中,發(fā)起了一條關(guān)于包管理器的投票,當(dāng)時(shí)筆者正混跡 pnpm 社區(qū),對此也有所耳聞,具體的投票結(jié)果可以參考:

          pnpm 作者本人 zkochan 對此結(jié)果還是很滿意的,因?yàn)橹敖y(tǒng)計(jì)社區(qū)的一些趨勢,pnpm 并沒有達(dá)到過如此高的使用率。

          隨著該條 twitter 之后,尤大又更新了一條 twitter (這里直接貼原文的內(nèi)容):

          esbuild 0.13 now uses optionalDependencies to install platform-specific binaries. Yarn 1/2 will download all binaries before picking the right one. Other (update to date) package managers only downloads the matching one.

          This may be the thing that pushes me away from Yarn 1 :/

          翻譯過來的內(nèi)容大概是 esbuild 在 v0.13 之后使用了optionalDependencies?來安裝某些不同平臺的依賴(相關(guān) pr 可以參考: https://github.com/evanw/esbuild/pull/1621)。但??yarn 1/2?并不會根據(jù)對應(yīng)的?optional?規(guī)則去下載對應(yīng)平臺的包而是會去選擇下載所有的包。

          那么為什么 esbuild 的一個(gè)調(diào)整會對尤大產(chǎn)生這樣的念頭呢,因?yàn)?vite 目前會在一些場景下使用到 esbuild 這個(gè)庫:例如目前開發(fā)階段 vite 會使用 esbuild 進(jìn)行依賴預(yù)打包,來將第三方依賴轉(zhuǎn)成 ESM 格式的 bundle 產(chǎn)物。

          這樣的關(guān)系使得 esbuild 作為了 vite 的一個(gè)底層依賴,前面也提到過 vite 本身倉庫是基于 yarn workspace monorepo 搭建的,因此每次在開發(fā) vite 時(shí)使用 yarn 安裝依賴的過程中,都會去安裝 esbuild 以及相關(guān)的包。

          下面筆者會詳細(xì)介紹一下 esbuild 的這個(gè)改動的原理以及為什么這個(gè)改動會使得 vite 將原有的 monorepo 架子直接做了遷移。

          依賴分發(fā)機(jī)制

          在上一節(jié)中提到了?esbuild?使用?optionalDependenceis?來作為目前的依賴安裝策略,這節(jié)來介紹一下像這樣這些跨平臺的包依賴分發(fā)的過程。

          其實(shí)關(guān)于這部分,具體可以參考社區(qū)中這篇:?用 Rust 和 N-API 開發(fā)高性能 Node.js 擴(kuò)展(文章地址: https://zhuanlan.zhihu.com/p/234914336)?文章最開頭的一部分內(nèi)容。

          這里筆者以 nodejs 原生拓展(native addon)的代碼分發(fā)方式為例子做個(gè)介紹:

          關(guān)于 nodejs 拓展開發(fā)可以參考筆者之前寫過的一篇文章:?Nodejs 的 C++ 拓展開發(fā)。

          其中主流的分發(fā)方式大概有這樣兩種:

          分發(fā) JS 代碼,postinstall 去下載對應(yīng)產(chǎn)物

          一般使用其他語言開發(fā)的 addon 之類的會把產(chǎn)物打包成一個(gè)可執(zhí)行的二進(jìn)制文件(例如 C++ 拓展一般是?.node?結(jié)尾的文件)。

          postinstall 腳本安裝的方式其實(shí)在社區(qū)中也是比較常見的,例如安裝 node-sass 就會按照這樣的模式進(jìn)行:

          node-sass?會把?native addon(C++ 開發(fā)) 的預(yù)編譯產(chǎn)物放在一個(gè) CDN 地址里面,然后用戶在使用?npm install?安裝?node-sass?的時(shí)候,會通過?postinstall?腳本將?addon?產(chǎn)物文件從 CDN 上下載下來。

          包括?v0.13?版本之前的?esbuild?其實(shí)也是采用這種方式來進(jìn)行分發(fā)。

          這種方式其實(shí)有個(gè)缺點(diǎn),可以看到圖中下載的二進(jìn)制文件地址是個(gè)?Github release?地址,這種情況下常常會因?yàn)闊o法兼顧國內(nèi)/海外用戶。不過一般可以通過在國內(nèi)搭建一個(gè)相關(guān)的下載鏡像來解決這個(gè)問題,但鏡像不同步的問題也是時(shí)常會發(fā)生的。

          不同平臺的?native addon?通過不同的 npm 包去分發(fā)

          目前市面上很火的兩個(gè)構(gòu)建工具,swc?和?esbuild?就采用的這種方式。每一個(gè)?native addon?對應(yīng)一個(gè)?npm?包。然后將所有的?native addon?對應(yīng)的?npm package?作為?optionalDependencies, 并在這些?npm package?的?package.json?中的?os?以及?cpu?字段,讓對應(yīng)的包管理工具在安裝的時(shí)候?qū)Σ煌脚_的包自動選擇去安裝哪個(gè)?native package,例如?esbuild?目前的 npm 包結(jié)構(gòu):

          {
          "name": "esbuild",
          "version": "0.14.1",
          "optionalDependencies": {
          "esbuild-android-arm64": "0.14.1",
          "esbuild-darwin-64": "0.14.1",
          "esbuild-darwin-arm64": "0.14.1",
          "esbuild-freebsd-64": "0.14.1",
          "esbuild-freebsd-arm64": "0.14.1",
          "esbuild-linux-32": "0.14.1",
          "esbuild-linux-64": "0.14.1",
          "esbuild-linux-arm": "0.14.1",
          "esbuild-linux-arm64": "0.14.1",
          "esbuild-linux-mips64le": "0.14.1",
          "esbuild-linux-ppc64le": "0.14.1",
          "esbuild-netbsd-64": "0.14.1",
          "esbuild-openbsd-64": "0.14.1",
          "esbuild-sunos-64": "0.14.1",
          "esbuild-windows-32": "0.14.1",
          "esbuild-windows-64": "0.14.1",
          "esbuild-windows-arm64": "0.14.1"
          }
          }

          例如其中對應(yīng)的?esbuild-android-arm64?一個(gè)安卓平臺的包,以及 arm64 架構(gòu)的包的?package.json?內(nèi)容為:

          {
          "name": "esbuild-android-arm64",
          "version": "0.14.1",
          "os": ["android"],
          "cpu": ["arm64"]
          }

          這種方式可以認(rèn)為是目前對使用?native addon?用戶影響最小的分發(fā)方式,包括這里提到的?esbuild、swc?以及?napi-rs?都是采用的這種方式。

          這種方式存在的缺點(diǎn)可能就是對開發(fā)者的負(fù)擔(dān)會比較大:因?yàn)樾枰瑫r(shí)維護(hù)多個(gè)系統(tǒng)以及 CPU 架構(gòu)的包。同時(shí)開發(fā)/調(diào)試也需要消耗很大的工作量。

          前面提到的 vite 底層的依賴項(xiàng)?esbuild?在?v0.13?之后由?postinstall script?安裝的方式遷移到了這種?optionalDependencies?的方式:

          包管理器支持

          在上一節(jié)中我們介紹到了?native addon?的一些常見的依賴分發(fā)機(jī)制,同時(shí)也介紹到了?esbuild?目前在?v0.13?之后采用了?optionalDependencies?機(jī)制。前面也有提到因?yàn)?yarn1?的依賴安裝機(jī)制問題導(dǎo)致在?vite?進(jìn)行開發(fā)時(shí),每次都會下載?esbuild?中所有的跨平臺包(例如在?android?平臺上也會下載 ios 的包),對此會導(dǎo)致每次給?vite?倉庫進(jìn)行依賴安裝的時(shí)候,耗費(fèi)很久的時(shí)間。參考?yarn?下面的?issue(https://github.com/yarnpkg/berry/issues/3317)。

          舉個(gè)例子來說(該例子來自于?esbuild?作者 evanw 解釋):

          以目前?pnpm v6.14?的行為來說,對于?esbuild?下的?optionalDep?進(jìn)行依賴安裝的時(shí)候,下面有各種跨平臺以及?cpu?架構(gòu)的包,但實(shí)際上只會對符合當(dāng)前平臺架構(gòu)的包進(jìn)行實(shí)際的依賴安裝,其他非這一類的包只是會生成一個(gè)?meta data?的數(shù)據(jù)在?lock?文件上。

          實(shí)際上包的體積時(shí)遠(yuǎn)遠(yuǎn)大于這份數(shù)據(jù)的大小(例如數(shù)據(jù)約?0.5MB,一個(gè)包大約?8MB),那么假設(shè)?optionalDep?下面存在 13 個(gè)?package,那么 pnpm 大概會安裝約?0.5mb * 13 + 8mb = 14.5mb?體積的包,而?yarnv1?則會安裝約?0.5mb * 12 + 8mb * 12 = 102mb?的包,這樣會使得因?yàn)榘芾砉ぞ卟煌那闆r下,yarn?安裝的東西比?pnpm?遠(yuǎn)多,從而導(dǎo)致依賴安裝的時(shí)間會很慢。

          關(guān)于上面提到的依賴安裝問題可以參考下表中的?Downloads extra data?這一欄,可以看到目前 yarn 只有?yarnv3.1.0?這個(gè)版本修復(fù)了該問題,pnpmnpm v7?以及?[email protected]?都解決了這個(gè)該問題。

          vue 生態(tài)項(xiàng)目完成遷移

          尤大在社區(qū)里面參考了一些開發(fā)者的意見以及發(fā)起了一個(gè)關(guān)于包管理器的投票,twitter?下?90%?左右的回復(fù)都推薦了?pnpm,包括目前?vue core team?的?antfu(https://github.com/antfu) 也已經(jīng)在自己的開源項(xiàng)目?slidev(https://github.com/slidevjs/slidev) 中實(shí)踐使用了?pnpm,同時(shí)也對?pnpm?的一些功能贊不絕口。

          于是 vite 直接在幾天之后開始了由?yarn workspace?到?pnpm workspace?的遷移:

          在遷移過程中雖然遇到了一些問題,但基本上隨著 pnpm 作者以及社區(qū)的幫助努力下,最后也都成功完成了,實(shí)際上的遷移成本也沒有特別的大,可以參考前面的 pr。

          在?vite?完成遷移之后,其他的?vue?生態(tài)項(xiàng)目也緊隨其后,雖然這些其他的項(xiàng)目底層可能沒有像?vite?遇到的?esbuild?的問題那樣,但?pnpm?的一些其他優(yōu)勢(例如對依賴的嚴(yán)格管理,快速的依賴安裝,天然的?monoreo workspace?支持等)也吸引著?vue?生態(tài)遷移了包管理工具。因?yàn)橛辛?vite?遷移的經(jīng)驗(yàn),其他項(xiàng)目的遷移也都很快完成了,基本上?vue3?的一個(gè)遷移相關(guān)的 mr 在一天的時(shí)間內(nèi)就完成了合并,慢慢地幾乎?vue?生態(tài)里面大部分項(xiàng)目都完成了遷移。

          遷移 pnpm 的實(shí)踐

          如果想了解如何從一個(gè)完整的?yarn workspace?項(xiàng)目遷移到?pnpm workspace,其實(shí)也不用去專門研究?vite?或者?vue3?的 pr 是怎么遷移的,在 pnpm 官網(wǎng)上有一篇來自于社區(qū)的文章: Replacing Lerna + Yarn with PNPM Workspaces (地址: https://www.raulmelo.dev/blog/replacing-lerna-and-yarn-with-pnpm-workspaces)。

          作者算是比較詳細(xì)的介紹了如果從yarn workspace(項(xiàng)目基于?lerna,但區(qū)別其實(shí)不大),遷移到?pnpm workspace?需要做的文件改動以及項(xiàng)目變更。大概是這樣的一個(gè)流程:

          • 替換掉腳本命令,與?yarn?相關(guān)的命令替換為:?pnpm ?或者?pnpm run

          • 刪除掉頂部?package.json?中的?yarn workspace?配置

          • 替換掉的?workspace?配置用?pnpm-workspace.yaml?文件替代

          • 調(diào)整?pipeline、以及?Dockfile?或者其他?CI/CD?配置文件里面的依賴安裝命令

          • 刪除掉?yarn.lock?文件(這里也可以使用筆者開發(fā)完善的?pnpm import?命令來完成?yarn.lock?文件轉(zhuǎn)換 /笑 )

          • 調(diào)整構(gòu)建相關(guān)的腳本(如果有?lerna?相關(guān)的?build?腳本)

          • 添加一個(gè)?.npmrc?文件用于自定義一些?pnpm?的?CLI?行為表現(xiàn)(也可以不用)

          感興趣的同學(xué)可以去參考一下,或者直接和筆者進(jìn)行交流也可以(筆者在字節(jié)也遷移過比較多這一類型的項(xiàng)目,對此也有一些經(jīng)驗(yàn),這里就不做過多的介紹了)。

          總結(jié)

          其實(shí)之前在尤大發(fā)起關(guān)于包管理工具的投票時(shí),筆者就已經(jīng)注意到了,同時(shí)也關(guān)注到了 vue 開始了 pnpm 的遷移,但當(dāng)時(shí)并沒有去仔細(xì)關(guān)注底層的原因。

          之前?yarn?的作者發(fā)布了?yarnv3.1(文檔見:?https://dev.to/arcanis/yarn-31-corepack-esm-pnpm-optional-packages--3hak),? 里面最吸引人注意的?feature? 可能是:?yarn?在這個(gè)版本下支持了?pnpm?模式的依賴安裝方式(即?content-addressable store),但?yarn?的作者表示這次版本發(fā)布中實(shí)現(xiàn)的最復(fù)雜的?feature?是支持了本文中提到的按需安裝不同平臺以及 cpu 架構(gòu)的依賴包:

          筆者在最近學(xué)習(xí) swc 的時(shí)候,注意到了這一點(diǎn),抱著刨根問底的心態(tài),去研究了一下這一系列遷移問題背后的原因(原因令人暖心)。

          最后寫了這樣一篇干貨性不是很強(qiáng)的文章,可以作為一個(gè)記錄如果之后有相關(guān)的需求進(jìn)行開發(fā)(例如使用其他語言開發(fā)?native addon?的時(shí)候)的話。同時(shí)也希望 pnpm 未來能成為一個(gè)社區(qū)中流行的包管理工具吧~

          最后



          如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我三個(gè)小忙:

          1. 點(diǎn)個(gè)「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點(diǎn)在看,都是耍流氓 -_-)

          2. 歡迎加我微信「qianyu443033099」拉你進(jìn)技術(shù)群,長期交流學(xué)習(xí)...

          3. 關(guān)注公眾號「前端下午茶」,持續(xù)為你推送精選好文,也可以加我為好友,隨時(shí)聊騷。


          點(diǎn)個(gè)在看支持我吧,轉(zhuǎn)發(fā)就更好了


          瀏覽 67
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  三级视频网址 | 欧美伊人 | 伊人大香蕉视频网 | 色色色综合 | 国产无码中文字幕 |