Skip to main content
Extension.js 會在開發與建置期間處理瀏覽器專屬的設定。你可以用同一個專案 為 Chromium 與 Gecko(Firefox 引擎)目標產出符合執行階段需求的輸出。

跨瀏覽器擴充功能開發

跨瀏覽器擴充功能開發指的是寫一個擴充功能,能同時上架到 Chrome、Edge 與 Firefox,而不需要分叉程式碼。Extension.js 會把單一專案編譯成各瀏覽器專屬的產物(dist/chromedist/edgedist/firefox),並依當前目標過濾 manifest。重新載入流程、執行階段 API 與打包行為都會對應你正在除錯的瀏覽器。 只使用一份 manifest.json,就能鎖定特定瀏覽器或自訂瀏覽器二進位檔。若你需要在 Chromium 家族目標中使用 browser.* API 相容性,可以啟用 polyfill。

Chrome 與 Firefox 擴充功能相容性

Chrome 與 Firefox 擴充功能共用大部分 WebExtensions 表面,但每天都會碰到三個關鍵差異:
  • 背景腳本: Chrome(Manifest V3)需要 background.service_worker。Firefox 則使用 background.scripts 搭配非持久的 event page。Extension.js 會在這兩種形態之間做雙向轉換,因此同一份 manifest 中兩種寫法都可行。
  • 執行階段 API 命名空間: Firefox 原生支援 browser.*,Chromium 使用 chrome.*。在 Chromium 目標可以加上 --polyfill 來彌平差異。
  • 權限與內容安全政策(CSP): 不同瀏覽器對某些 permissionshost_permissions 條目的判斷不同。將瀏覽器專屬的值放在帶前綴的 manifest 鍵內,而不是在執行階段做功能偵測。

瀏覽器專屬的 manifest 欄位

Extension.js 透過帶前綴的 manifest 欄位,讓單一份 manifest.json 在各瀏覽器上都能運作。在編譯時,Extension.js 會把帶前綴的鍵(chromium:chrome:edge:firefox:gecko:)過濾到當前目標,未加前綴的鍵則套用到所有目標。完整前綴清單請見 瀏覽器專屬的 manifest 欄位

範本範例

action

action template screenshot 用一個可在 Chrome、Firefox 與 Edge 執行的 action 彈出視窗,試試跨瀏覽器相容性。
儲存庫:extension-js/examples/action

運作方式

1) 選擇瀏覽器目標

選擇你要執行擴充功能的瀏覽器。 常見目標使用 --browser,或傳入自訂的瀏覽器二進位檔。
依你的作業系統使用對應的二進位檔路徑:
  • macOS/Applications/Brave Browser.app/Contents/MacOS/Brave Browser
  • Linux/usr/bin/brave-browser(或其他 Chromium 系瀏覽器的二進位檔)
  • Windows"C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe"
當你傳入二進位檔時,Extension.js 會把它對應到一個瀏覽器引擎目標:
  • --chromium-binary 對應 chromium-based
  • --gecko-binary 對應 gecko-based

2) 以瀏覽器專屬的 manifest 過濾進行編譯

在編譯時,Extension.js 只會包含你選定瀏覽器所需的 manifest 欄位。 例如:
對 Chromium 家族目標,Extension.js 會使用 chromium:chrome:edge: 等前綴。
對 Firefox 家族目標,Extension.js 會使用 firefox:gecko:
完整的帶前綴 manifest 欄位細節,請參閱 瀏覽器專屬的 manifest 欄位

background 的轉換是雙向的

常見情況下你不需要為 background 加前綴。Extension.js 會雙向轉換一般的 MV3 background
  • Gecko 建置若找到 background.service_worker 而沒有 background.scripts,會透過 scripts 把 background 重新指向產出的 bundle,並移除 Firefox 會拒絕的 service_workertype
  • Chromium MV3 建置若找到 background.scripts 且尚未設定 worker,會用第一個 script 來填入 service_worker
在 Chromium 這個方向,scripts 一律會從輸出中移除。只要出現 background.scripts,即使旁邊有合法的 service_worker,Chromium MV3 也會拒絕整個擴充功能,因此這個鍵永遠不能出現在 Chromium 建置中。

3) 為每個瀏覽器目標輸出

Extension.js 會把各目標寫入各自的建置資料夾:
  • dist/chrome
  • dist/edge
  • dist/firefox
  • dist/chromium(預設目標)
  • dist/chromium-based(自訂 Chromium 引擎)
  • dist/gecko-based(自訂 Gecko 引擎)
這讓你的建置產物結構分明,也更容易在 CI 中發佈。

4) Chromium 目標可選的 browser.* polyfill

如果你的程式碼使用 browser.*,可為 Chromium 家族目標啟用 --polyfill
啟用時,Extension.js 會在非 Firefox 目標使用 webextension-polyfill(Mozilla 的 browser.* 相容性函式庫)。
Firefox 本身已原生支援 browser.*,Extension.js 會略過這一步。
polyfill 模組會先從你的專案解析,接著才是 Extension.js 內建的相依套件。套件管理器可能會把 webextension-polyfill 提升到你的專案根目錄,而你自己安裝的那份會優先於內建的那份。若完全解析不到任何一份,建置會印出警告並在沒有 polyfill 的情況下繼續,而不是直接失敗。

最佳實務

  • 保持單一程式碼庫:可能的話,把瀏覽器差異放在帶前綴的 manifest 欄位裡。
  • 一次只建一個目標:在持續整合(CI)中為每個瀏覽器產出獨立的產物(dist/<browser>)。
  • 必要時才使用 --polyfillbuild 預設關閉,需要你明確傳入 --polyfilldevstart 則預設開啟。若你的程式碼不依賴 browser.*,在這兩個指令傳入 --no-polyfill 將其關閉。
  • 及早確認 API 支援:在依賴特定瀏覽器 API 前,先查閱 MDN WebExtensions 文件

下一步