The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

如何使用 esbuild 打包 JavaScript 應用程式

前幾天我透過 esbuild 解決了兩個小專案(side project)的 Bundling 問題,執行起來不但速度快,其上手的難度也比 webpack 還低,這篇文章將會介紹 esbuild 的基本使用方式。

image

安裝 esbuild 套件

npm install --save-exact --save-dev esbuild

查看版本

npx esbuild --version

替 Browser 應用程式打包

我之前替 Tampermoneky 寫了一個 ChatGPT 的 Userscript,可以替 ChatGPT 加上語音能力(語音合成與語音識別),但是我有動態載入 rxjs 這個 npm 套件,可惜近期 ChatGPT 加入了 CSP (Content Security Policy) 的限制,導致我無法從 cdn.jsdelivr.net 動態載入 rxjs,因此我必須將整份 rxjs 打包進去 Userscript 中才行!

還好這個過程並不複雜,我五分鐘就搞定了,步驟如下:

  1. 我主要的程式碼原本這樣寫

    const {
        Observable,
        catchError,
        defer,
        filter,
        fromEvent,
        interval,
        map,
        of,
        retry,
        shareReplay,
        Subject,
        switchMap,
        take,
        tap,
        timer
    } = await import('https://cdn.jsdelivr.net/npm/@esm-bundle/rxjs/esm/es2015/rxjs.min.js');
    
  2. 我改用 esbuild 打包的過程如下

    初始化 package.json

    npm init -y
    

    安裝 rxjs 套件

    npm install rxjs
    

    改寫我原本 JS 程式碼的 import 方式:

    import {
        Observable,
        catchError,
        defer,
        filter,
        fromEvent,
        interval,
        map,
        of,
        retry,
        shareReplay,
        Subject,
        switchMap,
        take,
        tap,
        timer
    } from 'rxjs';
    

    執行 esbuild 打包程式碼

    npx esbuild app.js --bundle --outfile=out.js --platform=browser
    

    就這麼簡單!

你還可以透過 --minify 參數對輸出 JS 進行最小化,加上 --sourcemap 則會自動產生 Source map 檔案,例如:

npx esbuild app.js --bundle --minify --sourcemap --outfile=out.js

注意: --platform 的預設值就是 browser,預設可以忽略不寫。

如果你想要針對特定瀏覽器版本進行打包,esbuild 還能自動幫你打包出符合特定瀏覽器版本的程式碼,例如:

npx esbuild app.js --bundle --minify --sourcemap --outfile=out.js --target=chrome58,firefox57,safari11,edge16

替 Node 應用程式打包

如果要替 Node 應用程式打包,只需要將 --platform 參數改成 node 即可,例如:

npx esbuild app.js --bundle --platform=node --target=node

如果要針對特定 Node 版本進行打包,也是沒問題的,例如:

npx esbuild app.js --bundle --platform=node --target=node10.4

另外,你也可以指定輸出的格式,例如:

npx esbuild app.js --bundle --platform=node --target=node --format=esm

--format 可設定的值有 iife, cjs, 與 esm

如果你不想將 Node 的外部依賴項目跟 esbuild 打包在一起,esbuild 在打包時不支援許多特定於 Node.js 的功能,例如 __dirname、import.meta.url、fs.readFileSync 和 *.node 原生二進制模組。您可以通過將 --packages 設定為 external 來排除所有相依檔案:

npx esbuild app.jsx --bundle --platform=node --packages=external

相關連結

留言評論