Skip to main content
tabs API 不需要打包工具做任何事。Extension.js 編譯 chrome.tabs 呼叫的方式和其他程式碼沒有兩樣。它真正改變的,是你在開發期間實際執行的那份 manifest,而這個差異裡藏著一個陷阱。

開發期會注入 tabs 權限

開發循環重新載入 content script 的方式,是把它們注入到已經開啟的分頁裡。這需要你的擴充功能可能沒有宣告的權限,所以 Extension.js 會把它們加進寫入 dist/ 的那份 manifest。 對於 manifest v3 專案,開發期會在 permissions 中加上:
它也會把所有 content script 的 match 樣式合併進 host_permissions 對於 manifest v2 專案,開發期加的是 tabsstorage,再加上那些 match 樣式,因為 manifest v2 沒有 host_permissions 這個鍵。 這些都不會進到正式環境。extension build 輸出的,剛好就是你宣告過的那些權限。 這個差異你可以自己看到。在 manifest.json 中只宣告 storage,然後比較兩次建置:
dist/chromium/manifest.json
dist/chromium/manifest.json

這個陷阱,以及如何避開

因為開發期注入了 tabs,即使 manifest.json 從未申請過這個權限,chrome.tabs.queryextension dev 中依然會成功。同一個呼叫在 extension build 之後就會失敗。 對某些 API,Extension.js 會為此發出警告。用了 chrome.management 卻沒有宣告它,建置就會告訴你:
這個警告涵蓋 storagescriptingmanagement它不涵蓋 tabs 一個呼叫 chrome.tabs 卻沒宣告權限的專案,編譯乾淨、開發期執行乾淨,然後在打包後的擴充功能裡壞掉。 用了什麼就宣告什麼:
manifest.json
接著在出貨前對著正式建置確認一次:
dist/chromium 以未封裝擴充功能的方式載入,再把功能實際跑一遍。

你真的需要 tabs 權限嗎?

很多擴充功能並不需要。tabs 權限的存在是為了讀取受保護的欄位,而不是為了呼叫這個 API。 activeTab 是比較小的請求。它授予的是使用者操作過的那個分頁的存取權,有效期就是那一次造訪。商店審核它的態度,比 tabs<all_urls> 寬厚得多。 完整清單請閱讀權限與主機權限

跨瀏覽器命名

Firefox 與 Safari 提供以 Promise 為基礎的 browser.tabs。Chromium 提供以 callback 為基礎的 chrome.tabs。Extension.js 透過 webextension-polyfill 在 Chromium 上提供 browser 命名空間,因此一種寫法到處都能用:
這是怎麼接上的,請閱讀跨瀏覽器相容性

從終端機指定單一分頁

有幾個 CLI 動詞作用於單一分頁。先列出開啟中的分頁:
每一列都帶有 id、URL、標題、是否作用中,以及視窗 id。把 id 傳進去:
--tab 只接受數字形式的分頁 id,其他都不行。若想改用網址來比對,請用 --url,它接受一個 match 樣式或一段單純的子字串:
兩個旗標都不給時,會使用最後取得焦點的視窗中的作用中分頁。 其他接受分頁的動詞:
這兩者的意思並不相同。在 reload 上,--tab 選的是動作對象。在 logs 上,它過濾的是已經記錄下來的事件。 extension storage 沒有 --tab 選項。請改用 --context 選擇介面。

失敗訊息

最後一條在 chrome:// 頁面與 Web Store 上很常見,任何擴充功能都碰不得那些頁面。

最佳實務

  • 要讀取分頁 URL 時就宣告 tabs。開發期不會提醒你。
  • 當工作由使用者手勢啟動時,優先選用 activeTab
  • 對著正式建置驗證權限,而不是開發建置。
  • 永遠不要假設分頁 id 能撐過瀏覽器重新啟動。請重新查詢一次。

後續步驟