Vite 雙引擎架構 —— Esbuild 概念篇

Vite 底層采用 雙引擎架構,核心構建引擎是 EsbuildRollup,二者在開發和生產環境中分工協作,共同實現高性能構建。不可否認,作為 Vite 的雙引擎之一,Esbuild 在很多關鍵的構建階段(如依賴預編譯TS 語法轉譯代碼壓縮)讓 Vite 獲得了相當優異的性能,是 Vite 高性能的得力助手。無論是在 Vite 的配置項還是源碼實現中,都包含了不少 Esbuild 本身的基本概念和高階用法。因此,要深入掌握 Vite,學習 Esbuild 必不可少。

本篇文章我將由?Esbuild 開始,講解 Vite 強大的雙引擎結構。強烈建議上手操作,讀兩三遍,不如上手寫一遍 。《esbuild 中文文檔》

🔍 一、為什么?Esbuild 的性能極高?

極速構建:

  • 性能碾壓傳統工具:基于 Go 語言編寫,多進程并行處理,比 Webpack/Rollup 快 10-100 倍(10個 three.js 副本打包僅需 0.39秒 vs Webpack 的 41秒) 。
  • 無緩存仍高效:內置優化算法,無需依賴緩存即可實現秒級編譯 。
    ?

開箱即用的支持:

  • 語言支持:原生處理 JS、TS、JSX、CSS(含 CSS Modules),無需額外配置 。
  • 模塊化:無縫捆綁 ESM 和 CommonJS 模塊,自動樹搖(Tree Shaking) 。
    ?

多場景適配:

  • 瀏覽器環境:默認輸出瀏覽器兼容代碼,支持?--minify?壓縮、--sourcemap?源碼映射 。
  • Node 環境:通過?--platform=node?打包,剝離 TS 類型、轉換 ESM→CommonJS 。

?🛠? 二、?Esbuild 安裝與使用

npm install esbuild  # 或 yarn add esbuild

1. 命令行調用

命令行方式調用也是最簡單的使用方式。我們先來寫一些示例代碼,新建src/index.jsx文件,內容如下:

import Server from "react-dom/server";let Greet = () => <h1>祝所有高三的同學,金榜題名!</h1>;
console.log(Server.renderToString(<Greet />));

注意安裝一下所需的依賴,在終端執行如下的命令:

npm install react react-dom

接著到package.json中添加build腳本:

 "scripts": {"build": "esbuild src/index.jsx --bundle --outfile=dist/out.js",},

現在,你可以在終端執行npm run build,可以發現如下的日志信息:

接著我們就可以看到dish目錄中的打包產物

?

說明我們已經成功通過命令行完成了 Esbuild 打包!但命令行的使用方式不夠靈活,只能傳入一些簡單的命令行參數,稍微復雜的場景就不適用了,所以一般情況下我們還是會用代碼調用的方式。

2. 代碼調用

Esbuild 對外暴露了一系列的 API,主要包括兩類: Build APITransform API,我們可以在 Nodejs 代碼中通過調用這些 API 來使用 Esbuild 的各種功能。想要更全面的了解的,可以去訪問文章開頭的文檔地址。

項目打包——Build API

Build API主要用來進行項目打包,包括buildbuildSync和?serve三個方法。

A、build?方法:異步打包

功能:執行異步構建任務,返回 Promise 對象,支持插件和并行操作。

適用場景:生產環境打包、復雜構建流程(如代碼分割、壓縮)。

首先我們來試著在 Node.js 中使用build 方法。你可以在項目根目錄新建build.js文件,內容如下:

import { build } from 'esbuild';async function runBuild() {// 異步方法,返回一個 Promiseconst result = await build({// ----  如下是一些常見的配置  --- // 當前項目根目錄absWorkingDir: process.cwd(),// 入口文件列表,為一個數組entryPoints: ["./src/index.jsx"],// 打包產物目錄outdir: "dist",// 是否需要打包,一般設為 truebundle: true,// 模塊格式,包括`esm`、`commonjs`和`iife`format: "esm",// 需要排除打包的依賴列表external: [],// 是否開啟自動拆包splitting: true,// 是否生成 SourceMap 文件sourcemap: true,// 是否生成打包的元信息文件metafile: true,// 是否進行代碼壓縮minify: false,// 是否開啟 watch 模式,在 watch 模式下代碼變動則會觸發重新打包watch: false,// 是否將產物寫入磁盤write: true,// Esbuild 內置了一系列的 loader,包括 base64、binary、css、dataurl、file、js(x)、ts(x)、text、json// 針對一些特殊的文件,調用不同的 loader 進行加載loader: {'.png': 'base64',}});console.log(result);
}runBuild();

隨后,你在命令行執行node build.js,就能在控制臺發現如下日志信息:

接著我們就可以看到dish目錄中的打包產物和相應的 SourceMap 文件

?

B、buildSync?方法:同步打包 (不推薦)

功能:同步執行構建任務,立即返回結果,但阻塞主線程

適用場景:小型項目、簡單腳本或 CLI 工具。

一個簡單的例子:

const result = esbuild.buildSync({entryPoints: ['app.js'],bundle: true,outfile: 'out.js',platform: 'node' // 指定 Node 環境
});if (result.errors.length > 0) {throw new Error('Build failed');
}

局限性

  • 性能影響:阻塞主線程,可能導致界面卡頓
  • 插件限制:Rollup 等工具的?buildSync?不支持插件
  • 適用性:僅推薦在輕量任務中使用

難道就不能使用同步打包了嗎??? ? ? ? ??如果說有,其實也是有的

使用?build?+?await?實現偽同步:

async function runBuild() {await esbuild.build({ /* 配置 */ });
}

?

C、serve?方法:開發服務器

這個 API 有 3 個特點。

  1. 開啟 serve 模式后,將在指定的端口和目錄上搭建一個靜態文件服務,這個服務器用原生 Go 語言實現,性能比 Nodejs 更高。

  2. 類似 webpack-dev-server,所有的產物文件都默認不會寫到磁盤,而是放在內存中,通過請求服務來訪問。

  3. 每次請求到來時,都會進行重新構建(rebuild),永遠返回新的產物。

下面,我們通過一個具體例子來感受一下。

// build.js
import { serve } from 'esbuild';function runBuild() {serve({port: 8000,servedir: './dist',onRequest: (args) => {if (args.path === '/') {args.path = '/index.html'}}},{absWorkingDir: process.cwd(),entryPoints: ["./src/index.jsx"],bundle: true,format: "esm",splitting: true,sourcemap: true,outdir: "dist",loader: {'.js': 'jsx','.png': 'file','.jpg': 'file'}}).then((server) => {console.log("HTTP Server starts at port", server.port);});
}runBuild();

1.運行構建命令

npm run build

2.啟動服務器

node build.js

我們在瀏覽器訪問http://localhost:8000/dist/index.js可以看到 Esbuild 服務器返回的編譯產物如下所示:

后續每次在瀏覽器請求都會觸發 Esbuild 重新構建,而每次重新構建都是一個增量構建的過程,耗時也會比首次構建少很多(一般能減少 70% 左右)。

Serve API 只適合在開發階段使用,不適用于生產環境。

單文件轉譯——Transform API

功能:對單個字符串內容進行轉換(如轉譯 TS/JSX),不訪問文件系統,適用于非文件環境(如瀏覽器內聯處理)或作為工具鏈一環。

Build API 類似,它也包含了同步和異步的兩個方法,分別是transformSynctransform

舉例栗子:在項目根目錄新建transform.js

// transform.js
import { transform, transformSync } from 'esbuild';async function runTransform() {// 第一個參數是代碼字符串,第二個參數為編譯配置const content = await transform("const isNull = (str: string): boolean => str.length > 0;",{sourcemap: true,loader: "tsx",});console.log(content);
}runTransform();

終端輸入:

node transform.js

接著你就會看見:

同樣的步驟,傳參:

// transform.js
import { transform, transformSync } from 'esbuild';async function runTransform(code = "const isNull = (str: string): boolean => str.length > 0;") {// 第一個參數是代碼字符串,第二個參數為編譯配置const content = await transform(code,{sourcemap: true,loader: "tsx",});console.log(content);
}const inputCode = process.argv[2];
runTransform(inputCode).catch(console.error);

終端輸入:

node transform.js "const add = (a: number, b: number): number => a + b;"

打印出:

由于同步的 API 會使 Esbuild 喪失并發任務處理的優勢(Build API的部分已經分析過),我同樣也不推薦大家使用transformSync。出于性能考慮,Vite 的底層實現也是采用 transform這個異步的 API 進行 TS 及 JSX 的單文件轉譯的。

📊 三、總結

Esbuild的優勢在于編譯速度非常快,且擁有Go語言的優勢,Go語言編寫的程序比JavaScript少了一個動態解釋的過程;在代碼實現上,Esbuild使用比較克制,很多在Webpack上使用插件實現的功能如loader、minify等均使用Go實現。;劣勢在于支持不完善,提供的功能很基礎,對代碼分割和css處理等支持較弱。

??優勢
  • 速度為王:Go 語言 + 并行處理 + 內置功能(減少 AST 轉換鏈) 。
    ?
  • 輕量 API:提供 CLI、JS、Go 三種接口,配置簡潔 。
    ?
  • 生產優化:默認支持 Tree Shaking、代碼壓縮、Source Map 。
??局限性

1.生態插件較弱

  • 不支持 Vue/Sass/Less 等語法,需 JS 插件(性能下降) 。
  • 無熱更新(HMR),依賴?--watch?或手動重啟 。

2.高級功能缺失

  • 無 AST 操作接口,無法實現類 Babel 按需引入 。
  • 代碼分割(Code Splitting)對非 ESM 包支持差 。
    ?

但是不可否認,它的作用和潛力,我相信 Esbuild 未來在持續迭代中, 生態完善后或顛覆前端構建范式。

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

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

相關文章

leetcode hot100 鏈表(二)

書接上回&#xff1a; leetcode hot100 鏈表&#xff08;一&#xff09;-CSDN博客 8.刪除鏈表的倒數第N個結點 class Solution { public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* currhead;int len0;while(curr){currcurr->next;len;}int poslen-n…

Compose Multiplatform 實現自定義的系統托盤,解決托盤亂碼問題

Compose Multiplatform是 JetBrains 開發的聲明式 UI 框架&#xff0c;可讓您為 Android、iOS、桌面和 Web 開發共享 UI。將 Compose Multiplatform 集成到您的 Kotlin Multiplatform 項目中&#xff0c;即可更快地交付您的應用和功能&#xff0c;而無需維護多個 UI 實現。 在…

C++11 Move Constructors and Move Assignment Operators 從入門到精通

文章目錄 一、引言二、基本概念2.1 右值引用&#xff08;Rvalue References&#xff09;2.2 移動語義&#xff08;Move Semantics&#xff09; 三、移動構造函數&#xff08;Move Constructors&#xff09;3.1 定義和語法3.2 示例代碼3.3 使用場景 四、移動賦值運算符&#xff…

Linux配置yum 時間同步服務 關閉防火墻 關閉ESlinux

1、配置yum 1.1、Could not resolve host: mirrorlist.centos.org; 未知的錯誤 https://blog.csdn.net/fansfi/article/details/146369946?fromshareblogdetail&sharetypeblogdetail&sharerId146369946&sharereferPC&sharesourceRockandrollman&sharefr…

使用 uv 工具快速部署并管理 vLLM 推理環境

uv&#xff1a;現代 Python 項目管理的高效助手 uv&#xff1a;Rust 驅動的 Python 包管理新時代 在部署大語言模型&#xff08;LLM&#xff09;推理服務時&#xff0c;vLLM 是一個備受關注的方案&#xff0c;具備高吞吐、低延遲和對 OpenAI API 的良好兼容性。為了提高部署效…

基于sqlite的任務鎖(支持多進程/多線程)

前言 介紹 任務鎖,在多進程服務間控制耗時任務的鎖,確保相同id的耗時任務同時只有一個在執行 依賴 SqliteOp,參考這篇文章 https://blog.csdn.net/weixin_43721000/article/details/137019125 實現方式 utils/taskLock.py import timefrom utils.SqliteOp import Sqli…

html表格轉換為markdown

文章目錄 工具功能亮點1.核心實現解析1. 剪貼板交互2. HTML檢測與提取3. 轉換規則設計 2. 完整代碼 在日常工作中&#xff0c;我們經常遇到需要將網頁表格快速轉換為Markdown格式的場景。無論是文檔編寫、知識整理還是數據遷移&#xff0c;手動轉換既耗時又容易出錯。本文將介紹…

IDEA 中 Undo Commit,Revert Commit,Drop Commit區別

一、Undo Commit 適用情況&#xff1a;代碼修改完了&#xff0c;已經Commit了&#xff0c;但是還未push&#xff0c;然后發現還有地方需要修改&#xff0c;但是又不想增加一個新的Commit記錄。這時可以進行Undo Commit&#xff0c;修改后再重新Commit。如果已經進行了Push&…

【Linux】Linux 進程間通訊-管道

參考博客&#xff1a;https://blog.csdn.net/sjsjnsjnn/article/details/125864580 一、進程間通訊介紹 1.1 進程間通訊的概念 進程通信&#xff08;Interprocess communication&#xff09;&#xff0c;簡稱&#xff1a;IPC 本來進程之間是相互獨立的。但是由于不同的進程…

深度剖析 DeepSeek 開源模型部署與應用:策略、權衡與未來走向

在人工智能技術呈指數級發展的當下&#xff0c;大模型已然成為推動各行業變革的核心驅動力。DeepSeek 開源模型以其卓越的性能和靈活的開源特性&#xff0c;吸引了眾多企業與開發者的目光。如何高效且合理地部署與運用 DeepSeek 模型&#xff0c;成為釋放其巨大潛力的關鍵所在&…

第34次CCF-CSP認證真題解析(目標300分做法)

第34次CCF-CSP認證 矩陣重塑&#xff08;其一&#xff09;AC代碼及解析矩陣重塑&#xff08;其二&#xff09;AC代碼及解析貨物調度AC代碼及解析 矩陣重塑&#xff08;其一&#xff09; 輸入輸出及樣例&#xff1a; AC代碼及解析 1.線性化原矩陣 &#xff1a;由于cin的特性我們…

智能制造數字孿生全要素交付一張網:智造中樞,孿生領航,共建智造生態共同體

在制造業轉型升級的浪潮中&#xff0c;數字孿生技術正成為推動行業變革的核心引擎。從特斯拉通過數字孿生體實現車輛全生命周期優化&#xff0c;到海爾卡奧斯工業互聯網平臺賦能千行百業&#xff0c;數字孿生技術已從概念驗證走向規模化落地。通過構建覆蓋全國的交付網絡&#…

【技術】跨設備鏈路聚合的技術——M-LAG

原創&#xff1a;廈門微思網絡 M-LAG&#xff08;Multichassis Link Aggregation Group&#xff09;提供一種跨設備鏈路聚合的技術。M-LAG通過將兩臺接入交換機以同一個狀態和用戶側設備或服務器進行跨設備的鏈路聚合&#xff0c;把鏈路的可靠性從單板級提升到設備級。同時&…

AI健康小屋+微高壓氧艙:科技如何重構我們的健康防線?

目前&#xff0c;隨著科技和社會的不斷發展&#xff0c;人們的生活水平和方式有了翻天覆地的變化。 從吃飽穿暖到吃好喝好再到健康生活&#xff0c;觀念也在逐漸發生改變。 尤其是在21世紀&#xff0c;大家對健康越來越重視&#xff0c;這就不得不提AI健康小屋和氧艙。 一、A…

Python訓練營---Day44

DAY 44 預訓練模型 知識點回顧&#xff1a; 預訓練的概念常見的分類預訓練模型圖像預訓練模型的發展史預訓練的策略預訓練代碼實戰&#xff1a;resnet18 作業&#xff1a; 嘗試在cifar10對比如下其他的預訓練模型&#xff0c;觀察差異&#xff0c;盡可能和他人選擇的不同嘗試通…

1.文件操作相關的庫

一、filesystem(C17) 和 fstream 1.std::filesystem::path - cppreference.cn - C參考手冊 std::filesystem::path 表示路徑 構造函數&#xff1a; path( string_type&& source, format fmt auto_format ); 可以用string進行構造&#xff0c;也可以用string進行隱式類…

【 java 集合知識 第二篇 】

目錄 1.Map集合 1.1.快速遍歷Map 1.2.HashMap實現原理 1.3.HashMap的擴容機制 1.4.HashMap在多線程下的問題 1.5.解決哈希沖突的方法 1.6.HashMap的put過程 1.7.HashMap的key使用什么類型 1.8.HashMapkey可以為null的原因 1.9.HashMap為什么不采用平衡二叉樹 1.10.Hash…

【Dify 知識庫 API】“根據文本更新文檔” 真的是差異更新嗎?一文講透真實機制!

在使用 Dify 知識庫 API 過程中,很多開發者在調用 /datasets/{dataset_id}/document/update-by-text 接口時,常常會產生一個疑問: ?? 這個接口到底是 “智能差異更新” 還是 “純覆蓋更新”? 網上的資料并不多,很多人根據接口名誤以為是增量更新。今天我結合官方源碼 …

大模型如何革新用戶價值、內容匹配與ROI預估

寫在前面 在數字營銷的戰場上,理解用戶、精準觸達、高效轉化是永恒的追求。傳統方法依賴結構化數據和機器學習模型,在用戶價值評估、人群素材匹配以及策略ROI預估等核心問題上取得了顯著成就。然而,隨著數據維度日益復雜,用戶行為愈發多變,傳統方法也面臨著特征工程繁瑣、…

基于端到端深度學習模型的語音控制人機交互系統

基于端到端深度學習模型的語音控制人機交互系統 摘要 本文設計并實現了一個基于端到端深度學習模型的人機交互系統,通過語音指令控制其他設備的程序運行,并將程序運行結果通過語音合成方式反饋給用戶。系統采用Python語言開發,使用PyTorch框架實現端到端的語音識別(ASR)…