manifest.json 編譯 content script 進入點,並用包裹器包起來以支援執行階段掛載與 hot module replacement(HMR)行為。最後會輸出可預測的 content_scripts/* 檔案。
Content script 能力
| 能力 | 你會獲得的成果 |
|---|---|
| 以 manifest 驅動的進入點 | 直接從 manifest 編譯 JS/CSS 的 content script 列表 |
| 開發期重新掛載流程 | 透過包裹器驅動的行為快速更新 script 與樣式 |
| MAIN 與 isolated world 支援 | 使用 MAIN world(頁面 JavaScript 情境)或 isolated world(沙箱化的擴充功能情境) |
| 可預測的輸出版面 | 輸出標準化的 content_scripts/* 產物 |
範本範例
content

content-react

支援的 manifest 欄位
| Manifest 欄位 | 預期檔案類型 |
|---|---|
content_scripts.js | .js, .jsx, .ts, .tsx, .mjs |
content_scripts.css | .css, .scss, .sass, .less |
Content script 宣告範例
在manifest.json 中宣告 content script 的範例:
撰寫合約
對於每一個類似 content script 的進入點,Extension.js 期待採用以「掛載」為模式的 default export。這是一個會設定行為、並可選擇性回傳清理 callback 的函式:- 模組應以
export default匯出一個同步函式。 - 該函式應執行設定工作。
- 它可以回傳一個同步的清理 callback。
- Extension.js 不支援將 class 作為 default export。
- 被
manifest.json > content_scripts[*].js參考的檔案。 - 你放在專案
scripts/資料夾中、用作 script 進入點的檔案。
有效形式
無效形式
對於 async content script 的建議
即使功能內部會做非同步工作,default export 仍應保持同步。在函式內部啟動非同步工作,並回傳同步的清理函式。 為什麼這很重要:Extension.js 會在開發期重新掛載 content script。若沒有清理函式,可能會重複出現 UI、事件監聽器、observer 與 timer。違反合約會發生什麼事
- 沒有 default export:Extension.js 會在開發期警告並跳過掛載。
- Default export 不是函式:Extension.js 會在開發期警告並跳過掛載。
- Default export 回傳一個 Promise:模組仍會執行,但 Extension.js 不會把該
Promise視為清理函式。
執行階段包裹器行為
- Extension.js 用掛載/runtime 輔助器包裹 content script 模組。
- 在開發模式中,Extension.js 會加上 HMR accept/dispose 行為與重新掛載流程。
- CSS 更新會在開發期觸發重新掛載事件(
__EXTENSIONJS_CSS_UPDATE__)。 - Extension.js 會尊重 manifest 中的
run_at時機設定。
多進入點 content script
你可以在單一 manifest 中宣告多個 content script 進入點。每個進入點都會獨立編譯,並擁有自己的 match patterns、執行時機與 world 設定。content-multi-one-entry

content_scripts manifest 進入點底下。
content-multi-three-entries

content_scripts manifest 進入點,各自有獨立的 match patterns。
scripts/ 資料夾行為
scripts/ 資料夾用來放沒有被任何 HTML 頁面進入點宣告的 script 進入點。實務上,這些進入點遵循與 content script 相同的 default export 模式。
也就是說,scripts/ 不是用來放零散 JavaScript 檔案的通用資料夾:
- Script 進入檔案如果需要掛載行為,仍應 export 一個 default function。
- 在 watch mode 中,Extension.js 把在
scripts/底下新增或刪除受支援檔案視為結構性變更。 - 當該進入點集合改變時,Extension.js 可能需要重新啟動開發伺服器。
輸出路徑
Extension.js 依 manifest 索引將 content script 進入點標準化:content-0.abcd1234.js)。這會強迫瀏覽器在每次重新建置後載入新的 chrome-extension:// URL。
Chrome 對擴充功能資源的快取相當積極,所以加上雜湊可以避免拿到舊程式碼。Production 建置會使用乾淨的 content-0.js 命名。
MAIN world 注意事項
content-main-world
透過將 UI 直接注入到頁面情境的可運作範例,看看 MAIN world content script 的實際表現:
world: "MAIN"僅限 Chromium。 Firefox 不支援world欄位並會忽略它。你的腳本在 Firefox 仍會以 isolated world 執行。- 跨瀏覽器的 MAIN world 行為: 使用
chromium:manifest 前綴,僅針對 Chromium 目標宣告它。然後為 Firefox 提供 isolated world 後備。 - 在開發期,MAIN world 腳本透過內部 bridge 機制載入程式碼 chunk 與解析 public path。
- 在 MAIN world 中無法使用擴充功能 API(
chrome.runtime、chrome.storage等);只能存取頁面情境的全域變數。 - 把 MAIN world 視為進階路徑。在每個目標瀏覽器上盡早驗證行為。
Isolated vs MAIN 快速範例
MAIN,並要考量擴充功能 API 與 runtime 的限制。
跨瀏覽器的 MAIN world 模式
使用瀏覽器專屬前綴,僅在 Chromium 上宣告 MAIN world,並為 Firefox 提供 isolated 後備:chromium: 前綴的欄位,所以只有 Chromium 目標會獲得 MAIN world 的 script。
比對與執行建議
瀏覽器仍然掌控 content script 在哪裡執行。Extension.js 會打包檔案,但 manifest 進入點仍然定義腳本執行的時機與位置。- 把
matches保持在功能所允許的最小範圍。 - 只在功能確實需要時才加入
exclude_matches、all_frames或match_about_blank。 - 把
run_at與world視為功能合約的一部分,而不是實作細節。 - 變更 content script 的執行位置時,重新測試權限與 host permission 的範圍。
開發行為
- 編輯 content script 程式碼通常會走包裹器驅動的 HMR/重新掛載流程。
- 純 CSS 進入點會獲得開發輔助行為,讓樣式更新得以傳播。
- 如果 manifest 中的 content script 進入點清單改變,Extension.js 可能需要重新啟動開發伺服器。
最佳實務
- 讓 content script 進入檔案保持小巧,把邏輯委派給共用模組。
- 仔細限定 selector/樣式範圍,避免與主機頁面衝突。
- 當行為依賴執行時機/情境時,明確設定
run_at與world。 - 在開發流程中,把 manifest content script 清單變更視為結構性變更。
- 透過經過驗證的 messaging 傳遞來自頁面的資料,而不是直接在 content script 中執行特權工作。
- 預設使用 isolated world,只有在嚴格需要頁面情境時才改用
MAIN。
後續步驟
- 在 dev 更新行為中了解更新結果。
- 透過 Messaging 設計跨情境通訊。
- 在權限與 host 權限中檢視存取範圍。
- 了解 web-accessible resources。
- 繼續閱讀開發中的 locale。

