自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Vite 是怎樣利用 Esbuild 來提升性能的 ?

開發(fā) 前端
今天小編就通過本文和大家一起聊一聊 Vite 是怎樣利用 Esbuild 來提升性能的。

前言

在上一篇 為什么有人說 vite 快,有人卻說 vite 慢?[1] 中,我們提到過開發(fā)模式下使用 Vite 會(huì)有首屏性能下降的負(fù)面效果。之所以會(huì)造成首屏性能下降,一方面是 dev server 需要完成預(yù)構(gòu)建才可以響應(yīng)首屏請(qǐng)求;另一方面是需要對(duì)請(qǐng)求文件做實(shí)時(shí)轉(zhuǎn)換。

也許有的同學(xué)會(huì)問,是不是針對(duì)這兩個(gè)方面做優(yōu)化,就可以提升首屏性能呢?原則上這樣是沒有問題的,而且 Vite 也是這么做的。為了能提升性能,Vite 另辟蹊徑的借助了 Esbuild 能快速完成項(xiàng)目打包、文件轉(zhuǎn)換的能力來進(jìn)行預(yù)構(gòu)建、內(nèi)容轉(zhuǎn)換,效果非常好。

今天小編就通過本文和大家一起聊一聊 Vite 是怎樣利用 Esbuild 來提升性能的。

本文的目錄結(jié)構(gòu)如下:

  •  初探 Esbuid[2]
  •  什么是 Esbuild[3]
  •  關(guān)鍵 API \- transform \& build[4]
  •  plugin[5]
  •  Esbuild 在 Vite 中的巧妙使用[6]
  •  預(yù)構(gòu)建[7]
  •  middlewares 中內(nèi)容轉(zhuǎn)換[8]
  •  結(jié)束語

初探 Esbuild

首先,小編先帶大家簡單了解一下 Esbuild,其官方地址是: **Esbuild[9]**。

什么是 Esbuild

Esbuild 是一款基于 Go 語言開發(fā)的 javascript 打包工具,最大的一個(gè)特征就是快。

通過官網(wǎng)提供的一張圖,我們可以清晰的看到 Esbuild 的表現(xiàn)是多么優(yōu)秀:

image.png

同樣規(guī)模的項(xiàng)目,使用 Esbuild 可以將打包速度提升 10 - 100 倍,這對(duì)廣大一直飽受 Webpack 緩慢打包速度折磨的開發(fā)人員來說,簡直就是福音。

而 Esbuild 之所以能這么快,主要原因有兩個(gè):

  •  Go 語言開發(fā),可以多線程打包,代碼直接編譯成機(jī)器碼;
  •   Webpack 一直被人詬病構(gòu)建速度慢,主要原因是在打包構(gòu)建過程中,存在大量的 resolve、load、transform、parse 操作(詳見 為什么有人說 vite 快,有人卻說 vite 慢?- 快速的冷啟動(dòng)[10] ),而這些操作通常是通過 javascript 代碼來執(zhí)行的。要知道,javascript 并不是什么高效的語言,在執(zhí)行過程中要先編譯后執(zhí)行,還是單線程并且不能利用多核 cpu 優(yōu)勢(shì),和 Go 語言相比,效率很低。
  •  可充分利用多核 cpu 優(yōu)勢(shì);

關(guān)鍵 API - transfrom & build

Esbuild 并不復(fù)雜。它對(duì)外提供了兩個(gè) API - transform 和 build,使用起來非常簡單。

transfrom,轉(zhuǎn)換的意思。通過這個(gè) api,我們可以將 ts、jsx、tsx 等格式的內(nèi)容轉(zhuǎn)化為 js。transfrom 只負(fù)責(zé)文件內(nèi)容轉(zhuǎn)換,并不會(huì)生成一個(gè)新的文件。

build,構(gòu)建的意思,根據(jù)指定的單個(gè)或者多個(gè)入口,分析依賴,并使用 loader 將不同格式的內(nèi)容轉(zhuǎn)化為 js 內(nèi)容,生成一個(gè)或多個(gè) bundle 文件。

這兩個(gè) API 的使用方式:

const res = await esbuild.transform(code, options) // 將 code 轉(zhuǎn)換為指定格式的內(nèi)容
esbuild.build(options) // 打包構(gòu)建
復(fù)制代碼

關(guān)于使用 transform、build 需要傳入的具體配置項(xiàng),本文就不詳細(xì)說明了,官網(wǎng)對(duì)這一塊兒有很詳細(xì)的說明,感興趣的同學(xué)可以去官網(wǎng) - simple-options[11]、Advanced options[12] 看看,也可以自己動(dòng)手試試。

plugin

和 Webpack、Rollup 等構(gòu)建工具一樣,Esbuild 也提供了供外部使用的 plugin,使得我們可以介入構(gòu)建打包過程。

  •  在這里要說明一點(diǎn),只有 build 這個(gè) API 的入?yún)⒅锌梢耘渲?plugin,transform 不可以。

一個(gè)標(biāo)準(zhǔn)的 plugin 的標(biāo)準(zhǔn)格式如下:

let customerPlugin = {
name: 'xxx',
setup: (build) => {
build.onResolve({ filter: '', namespace: '' }, args => { ...});
build.onLoad({ filter: '', namespace: ''}, args => { ... });
build.onStart(() => { ... });
build.onEnd((result) => { ... });
}
}
復(fù)制代碼

其中,setup 可以幫助我們?cè)?build 的各個(gè)過程中注冊(cè) hook。

Esbuild 對(duì)外提供的 hook 比較簡單,總共 4 個(gè):

  •  onResolve, 解析 url 時(shí)觸發(fā),可自定義 url 如何解析。如果 callback 有返回 path,后面的同類型 callback 將不會(huì)執(zhí)行。所有的 onResolve callback 將按照對(duì)應(yīng)的 plugin 注冊(cè)的順序執(zhí)行。
  •  onLoad, 加載模塊時(shí)觸發(fā),可自定義模塊如何加載。如果 callback 有返回 contents,后面的同類型 callback 將不會(huì)執(zhí)行。所有的 onLoad callback 將按照對(duì)應(yīng)的 plugin 注冊(cè)的順序執(zhí)行。
  •  onStart, 每次 build 開始時(shí)都會(huì)觸發(fā),沒有入?yún)?,因此不具有改?build 的能力。多個(gè) plugin 的 onStart 并行執(zhí)行。
  •  onEnd, 每次 build 結(jié)束時(shí)會(huì)觸發(fā),入?yún)?build 的結(jié)果,可對(duì) result 做修改。所有的的 onEnd 將按照對(duì)應(yīng)的 plugin 注冊(cè)的順序執(zhí)行。

正是有了 onResolve、onLoad、onStart、onEnd,我們可以在 build 過程中的解析 url、加載模塊內(nèi)容、構(gòu)建開始、構(gòu)建結(jié)束階段介入,做自定義操作。

Esbuild 在 Vite 中的巧妙使用

了解了 Esbuild 的基本用法以后,小編就帶大家一起來看看 Vite 是怎么利用 Esbuild 來做預(yù)構(gòu)建和內(nèi)容轉(zhuǎn)換的。

預(yù)構(gòu)建

先來回顧一下為什么要做預(yù)構(gòu)建。

原因有兩點(diǎn):

  •  將非 ESM 規(guī)范的代碼轉(zhuǎn)換為符合 ESM 規(guī)范的代碼;
  •  將第三方依賴內(nèi)部的多個(gè)文件合并為一個(gè),減少 http 請(qǐng)求數(shù)量;

要完成預(yù)構(gòu)建,最關(guān)鍵的兩點(diǎn)是找到項(xiàng)目中所有的第三份依賴和對(duì)第三方依賴做合并、轉(zhuǎn)換。借助 Esbuild,Vite 很輕松的實(shí)現(xiàn)了這兩個(gè)訴求。

  •  尋找第三方依賴

尋找第三方依賴的過程非常簡單,分為兩步:

和 Webpack、Rollup、Parcel 等構(gòu)建工具一樣,Esbuild 在做打包構(gòu)建時(shí)也要構(gòu)建模塊依賴圖 - module graph(具體過程可參考 為什么有人說 vite 快,有人卻說 vite 慢?- 快速的冷啟動(dòng)[13] 中 Webpack 構(gòu)建 module graph)。

在構(gòu)建 module graph 時(shí),第一步就是解析模塊的絕對(duì)路徑,這個(gè)時(shí)候就會(huì)觸發(fā) onResolve hook。在 onResolve hook 觸發(fā)時(shí),會(huì)傳入模塊的路徑。根據(jù)模塊的路徑,我們就可以判斷出這個(gè)模塊是第三方依賴還是業(yè)務(wù)代碼。

   舉個(gè) ??,

// main.tsx
import react from 'react';
import CustomeComponent from './components/CustomeComponent';
...
復(fù)制代碼

在對(duì) main.tsx 的內(nèi)容做 parser 操作時(shí),能知道 main.tsx 依賴 react 和 CustomeComponent,然后開始解析 react 和 CustomeComponent。

解析 react、CustomeComponent 時(shí),會(huì)觸發(fā) onResolve hook,入?yún)⒎謩e為 'react' 和 './components/CustomeComponent'。根據(jù)入?yún)?,我們可以很清楚的區(qū)分 'react' 是第三方依賴,'./components/CustomeComponet' 是業(yè)務(wù)代碼。

這樣,esbuild 完成構(gòu)建,項(xiàng)目中的第三方依賴也就收集完畢了。所有的第三方依賴會(huì)收集到一個(gè) deps 列表中。

  1.   定義一個(gè)帶 onResolve hook 和 onLoad hook 的 esbuild plugin;
  2.   執(zhí)行 esbuild 的 build 方法做打包構(gòu)建;
  •  合并、轉(zhuǎn)換第三方依賴

知道了項(xiàng)目中的第三方依賴以后,再做合并、轉(zhuǎn)換操作就非常簡單了。

這一步, Vite 直接通過 esbuild 提供的 build 方法,指定 entryPoints 為收集到的第三方依賴,format 為 esm,再做一次打包構(gòu)建。

這一次,會(huì)對(duì)第三方依賴做合并、轉(zhuǎn)換操作。打包構(gòu)建完成以后,再把構(gòu)建內(nèi)容輸出到 /node_modules/.vite/deps 下。

這樣,通過兩次 esbuild.build,預(yù)構(gòu)建就完成了。

middlewares 中內(nèi)容轉(zhuǎn)換

Vite 中源文件的轉(zhuǎn)換是在 dev server 啟動(dòng)以后通過 middlewares 實(shí)現(xiàn)的。

當(dāng)瀏覽器發(fā)起請(qǐng)求以后,dev sever 會(huì)通過相應(yīng)的 middlewares 對(duì)請(qǐng)求做處理,然后將處理以后的內(nèi)容返回給瀏覽器。

middlewares 對(duì)源文件的處理,分為 resolve、load、transform、parser 四個(gè)過程:

  1.    resolve - 解析 url,找到源文件的絕對(duì)路徑;
  2.    load - 加載源文件。如果是第三方依賴,直接將預(yù)構(gòu)建內(nèi)容返回給瀏覽器;如果是業(yè)務(wù)代碼,繼續(xù) transform、parser。
  3.    transfrom - 對(duì)源文件內(nèi)容做轉(zhuǎn)換,即 ts -> js, less -> css 等。轉(zhuǎn)換完成的內(nèi)容可以直接返回給瀏覽器了。
  4.    parser - 對(duì)轉(zhuǎn)換以后的內(nèi)容做分析,找到依賴模塊,對(duì)依賴模塊做預(yù)轉(zhuǎn)換 - pre transform 操作,即重復(fù) 1 - 4。

pre transform 是 Vite 做的一個(gè)優(yōu)化點(diǎn)。預(yù)轉(zhuǎn)換的內(nèi)容會(huì)先做緩存,等瀏覽器發(fā)起請(qǐng)求以后,如果已經(jīng)完成轉(zhuǎn)換,直接將緩存的內(nèi)容返回給瀏覽器。

Vite 在處理步驟 3 時(shí),是通過 esbuild.transform 實(shí)現(xiàn)的,對(duì)比 Webpack 使用各個(gè) loader 處理源文件,那是非常簡單、快捷的。

結(jié)束語

有一說一,Vite 通過 Esbuild 來優(yōu)化預(yù)構(gòu)建和內(nèi)容轉(zhuǎn)換的思路非常棒,這給我們以后處理同類問題提供了解決方案,真心給尤大點(diǎn) ????。

另外除了使用 Esbuild, Vite 內(nèi)部還有很多可以拿出來單獨(dú)講的優(yōu)化技巧,這個(gè)以后有機(jī)會(huì)小編可以再給大家詳細(xì)講講。

責(zé)任編輯:龐桂玉 來源: 前端進(jìn)階之旅
相關(guān)推薦

2023-04-10 09:15:25

Vite 4.3SWC 插件

2022-02-24 10:42:32

JavaScript開發(fā)報(bào)告

2015-01-21 15:40:44

GoRuby

2021-05-08 08:35:33

Webpack前端性能

2016-10-27 08:39:35

大數(shù)據(jù)設(shè)計(jì)定量

2015-05-29 14:01:00

網(wǎng)絡(luò)優(yōu)化網(wǎng)絡(luò)性能

2025-01-13 00:00:00

2015-06-01 10:14:13

微服務(wù)AWS性能彈性計(jì)算云

2022-10-15 07:49:18

代碼虛擬線程

2021-09-27 09:52:41

FacebookBOLTLinux

2016-09-26 13:50:52

Linux系統(tǒng)性能

2011-08-09 17:15:45

注冊(cè)表注冊(cè)表編輯器

2010-03-19 09:22:37

至強(qiáng)5600

2009-03-22 19:19:15

多核多核服務(wù)器多核歷史

2013-07-24 15:33:57

紅帽

2014-07-04 09:58:15

gemsRails

2022-02-24 07:56:42

開發(fā)Viteesbuild

2024-11-28 10:26:32

2023-04-21 10:10:07

Vite 4.3前端

2024-03-08 08:40:25

點(diǎn)贊
收藏

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