Manifest V3 背景的 service_worker 搭配 type: "module"
Chromium 在 MV3 的背景採用 service worker。若要從中 import ES module,manifest 需設定 type: "module":
"type": "module",import 陳述句會在註冊時失敗,而且擴充功能主控台不會出現明確錯誤。加上之後,你就能在 worker 檔案中撰寫現代 ES module 語法。
當你的背景進入點使用 ES module 語法時,Extension.js 會自動設定 type: "module"。它也會把 .ts/.tsx worker 編譯成單一打包輸出,讓 module 解析在正式環境中仍能正常運作。
為什麼 background.js 在 Manifest V3 行為不同
在 Manifest V2 中,background.js 在常駐的背景頁面執行,具有 DOM。在 Chromium 上的 Manifest V3,背景則以 service worker 執行:
- 沒有 DOM。
window、document、XMLHttpRequest與localStorage都不存在。請改用fetch與chrome.storage。 - worker 隨時可能在閒置時被終止,並在下一次事件喚醒。不要將狀態存在 module 範圍變數中;請持久化到
chrome.storage。 - 允許頂層
await,但長時間初始化本身無法讓 worker 維持存活。 - 在檔案最上方同步註冊事件監聽器,不要放在 async callback 內。註冊在 async callback 內的監聽器,不會在喚醒 worker 的那次事件中觸發。
service_worker、Firefox 路由到 scripts,共用同一份原始碼,使同一個背景進入點能依目標正確編譯。
Manifest V3 的 web_accessible_resources
Manifest V3 把 web_accessible_resources 從扁平字串陣列改為 { resources, matches } 區塊清單:
- 列出不在建置輸出裡的路徑。Extension.js 只會輸出被
manifest.json、進入點 HTML 或被 import 程式碼引用的檔案。請把該檔案加為資產,讓它落到dist/<browser>。 - 忘了
matches。少了它,資源不會暴露給任何來源。 - 使用 V2 風格的扁平字串。瀏覽器在 MV3 會安靜忽略這些。
web_accessible_resources 實作。
host_permissions 與 permissions
Manifest V3 把主機存取從 permissions 陣列拆出來:
| 鍵 | 控管的內容 |
|---|---|
permissions | 具名 API 介面(storage、tabs、cookies、scripting、alarms 等)。 |
host_permissions | 擴充功能可以讀取或修改的 URL match 樣式(https://*/*、*://api.example.com/*)。 |
optional_permissions 與 optional_host_permissions | 在執行期透過 chrome.permissions.request 請求的權限。 |
- 對你擁有存取權的網站呼叫
chrome.cookies.get回傳空結果:該 URL 需要host_permissions,光有cookies不夠。 chrome.scripting.executeScript出現 “Cannot access contents of url”:請把該 URL 加入host_permissions。- 你只需要一個來源時,Web Store 卻警告使用者擁有「全站」存取權:請收斂主機樣式。
Firefox 的 declarative_net_request
declarative_net_request(DNR)是 MV3 用來取代封鎖型 webRequest 的方案。Firefox 支援它,但有幾項限制:
- 靜態規則資源檔(
rule_resources)必須是有效的 JSON 陣列。Firefox 對於空或格式錯誤的規則檔比 Chrome 更嚴格。 - Chrome 支援的部分規則動作與條件在 Firefox 仍是部分支援。最新的對應表請參閱 MDN 的
declarativeNetRequest文件。 - 跨來源請求要套用 DNR 規則,必須有
host_permissions(或<all_urls>)。
Content script、worker 與擴充功能 URL
三個 MV3 容易讓人踩雷的地方:- Content script 無法存取頁面的 JavaScript scope。 它們共享 DOM,但不共享 window。請用
window.postMessage(或指向web_accessible_resources項目的<script>標籤)與頁面程式碼溝通。 - service worker 在安裝過程中無法可靠呼叫
chrome.runtime.getURL。 請在需要 URL 的事件處理函式內延後解析。 - 擴充功能 URL 以 origin 為界。 你擴充功能中的兩個頁面之間可以互相對話,但網頁無法從外部抓取它們,除非它們列在
web_accessible_resources中。
Extension.js 如何協助處理 Manifest V3
- 自動把背景進入點路由到
service_worker(Chromium)或scripts(Firefox)。 - 當背景使用 ES module 語法時,自動設定
type: "module"。 - 在建置期針對作用中的 manifest 版本驗證
web_accessible_resources、permissions與host_permissions。 - 輸出每個瀏覽器專屬的
dist/<browser>成品,讓 Chrome 與 Firefox 之間的 MV3 差異彼此隔離。 - 在
extension dev期間,儲存時重新載入 content script、service worker 與 HTML 頁面。
下一步
- 閱讀權限與主機權限。
- 閱讀背景腳本與Content scripts。
- 閱讀
web_accessible_resources。 - 建置流程請見跨瀏覽器相容性。
- 加上前綴的 manifest 鍵請見瀏覽器專屬的 manifest 欄位。
- 各瀏覽器擴充功能框架如何處理 MV3 差異。

