這篇文章對 esbuild 在 vite 中的應(yīng)用做一個總結(jié)
vite 中 esbuild 的應(yīng)用
esbuild 是 vite 性能快的關(guān)鍵汰聋。esbuild 在 vite 中主要被使用在以下場景:
- 通過入口分析依賴樹,收集 node_modules 中的依賴庐船,提前打包處理歇万,并在磁盤持久化緩存處理過后的文件。
- 對部分業(yè)務(wù)文件 使用 esbuild 處理轉(zhuǎn)化闸溃,比如 ts整吆、jsx、tsx辉川。注意 js 類型文件并不會被處理
node_modules 處理
需要處理 node_modules 的原因:
- 第三方庫代碼不會經(jīng)常變動表蝙,緩存處理,提高響應(yīng)速度乓旗。
- 打包第三方庫府蛇,使 lodash 這種文件較多的庫,減少網(wǎng)絡(luò)請求寸齐。
- 代碼兼容處理:比如有的依賴代碼模塊格式并不是 esm 而是 commonjs欲诺,利用 esbuild 進行模塊格式轉(zhuǎn)換。
難點一:vite 如何從 index.html 入口分析依賴的組成渺鹦?他怎么知道需要處理哪些包?
- esbuild 天生支持 index.html 作為入口打包
require('esbuild').buildSync({
entryPoints: ['index.html'], // is ok
bundle: true,
write: true,
outdir: 'out',
})
if (resolved.includes('node_modules') || include?.includes(id)) {
if (OPTIMIZABLE_ENTRY_RE.test(resolved)) {
// esbuild 插件中直接判斷引入的包是否是 node_modules 中的依賴
depImports[id] = resolved
}
}
難點二:esbuild 如何處理 vue 等非 javascript 文件蛹含,并無官方 vue-loader
const regex = isHtml ? scriptModuleRE : scriptRE
const scriptModuleRE =
/(<script\b[^>]*type\s*=\s*(?:"module"|'module')[^>]*>)(.*?)<\/script>/gims
export const scriptRE = /(<script\b(?:\s[^>]*>|>))(.*?)<\/script>/gims
vite 內(nèi)部通過編寫一個簡單的 esbuild 插件毅厚,直接利用正則表達式將 script 標簽內(nèi)部內(nèi)容截取出來,作為 vue 文件的內(nèi)容浦箱。這樣 esbuild 就可以將 vue 文件當成 js 文件處理依賴樹了吸耿。
編譯業(yè)務(wù)文件
當用戶第一次請求業(yè)務(wù)文件的時候,瀏覽器以及 vite 應(yīng)用內(nèi)部均沒有緩存酷窥,這個時候就要倚靠 esbuild 對部分業(yè)務(wù)文件進行編譯咽安。
esbuild 默認會編譯 ts、tsx蓬推、jsx 文件妆棒。
其中 js 文件默認不會被編譯。所以當選擇一些新語法開發(fā)時沸伏,要慎重
語法兼容問題
瀏覽器兼容
就像剛才說的問題糕珊,普通的 js 文件以及 vue 文件中的 js script 內(nèi)容,是不會被 esbuild 處理編譯的毅糟,所以不穩(wěn)定的新語法是不能在 vite 環(huán)境下使用的红选。
esbuild 兼容
esbuild 作為新起的打包工具,他對部分語法是不支持的姆另,比如 js 文件中使用裝飾器喇肋。這個場景 esbuild 就是不兼容的坟乾。
所以語法兼容問題要考慮兩個問題:
- 你開發(fā)時用的瀏覽器最好是比較新的 chrome 或者火狐瀏覽器,因為 vite 并不會默認編譯 js 文件蝶防,如果有兼容問題糊渊,處理起來比較復(fù)雜。
- 代碼兼容也要考慮 esbuild 的語法支持程度慧脱。如果有 esbuild 不支持的語法渺绒,在 vite 提前打包 node_modules 文件時會直接報錯。(vite 會在啟動服務(wù)的時候菱鸥,默認從入口查找所有需要打包的 node_modules 文件宗兼,如果你的業(yè)務(wù)代碼有兼容問題,會導(dǎo)致 esbuild 分析文件直接報錯氮采。)