Skip to main content
每次檔案變更使用最輕量的更新策略,讓開發節奏快速。 每次檔案變更後想要快速回饋?Extension.js 會自動選擇最安全、最快速的更新路徑:
  • HMR(hot module replacement):當模組更新是安全的時候
  • 分類重載(full、service worker、content scripts,或僅通知的 page):當執行階段資產有變更時
  • 需要重啟的錯誤/警告:當 entry 結構有變更時

重新載入前置條件(devtools 設定對話框)

在評估重新載入行為之前,先確認 Extension.js devtools 的 Confirm setup 對話框所列的相同設定檢查: 如果你跳過任一步驟,即使建置流水線健康,重新載入行為也可能看起來不一致。

重新載入層級

1) Hot module replacement(最快路徑)

當程式碼可以更新而不需重啟擴充功能的背景程序與事件監聽器時,Extension.js 會使用 HMR。 常見例子:
  • 附加在擴充功能 HTML 頁面上的腳本(透過注入的 HMR 包裝接受更新)
  • 非 service worker 流程中的背景腳本模組
  • 透過 userScripts API 註冊的腳本
  • 在支援的 content-script/runtime 包裝中的 CSS 更新

2) 分類重載

當一次變更需要的不只是 HMR 時,Extension.js 會把它歸入四種重載類型其中之一: 這個判定來自編譯器的 chunk 圖,而不是檔名,並遵循固定順序:
  1. 強制 full。manifest.json_locales/ 底下任何內容的變更,一律歸類為 full,不論還改了什麼。
  2. Chunk 歸屬。 Extension.js 會查出每個變更來源檔屬於哪些 chunk。位於 background/ chunk 的來源檔代表 service-worker,位於 content_scripts/ chunk 的來源檔代表 content-scripts
  3. 變更的靜態資產。 有些變更檔案存在於輸出目錄,卻不屬於任何 chunk:圖示、web-accessible 資源、DNR 規則集。它們會強制 full,讓瀏覽器從磁碟重新讀取。
  4. 名稱啟發式。 僅用於 chunk 圖不認識的來源檔:路徑符合 backgroundservice worker 樣式的歸類為 service-worker
  5. Content 後備。 若 manifest 宣告了 content script,其餘未知的變更會重新注入每一個 content-script entry。
  6. 僅通知的 page。 其他一切都是 page 指令:重新整理由 livereload 負責,重載通告仍會發出。
同時存在於 service-worker chunk 與 content-script chunk 的來源檔會向兩條路徑扇出。一次儲存會觸發 SW 重新啟動,並在同一份分類指令中帶上待重新注入的過期 content-script entry。 每次開發階段的重載都會由開發伺服器產生單一的情境標籤來通告。格式是 context (fileA, fileB +2 more),例如 service_worker + content_script (shared/api.ts)。同一個標籤會原封不動出現在 CLI 的 stdout、頁面 devtools 主控台與 devtools 標籤中,讓你不必猜測就能在三處對應同一次重載。
如果瀏覽器在重載後仍提供過期的快取 service worker,開發伺服器會偵測到版本不一致並自動重新同步擴充功能。你不需要手動移除再重新加入擴充功能才能恢復。
為什麼開發階段的 content script 檔名會包含雜湊? Chrome 會積極快取 chrome-extension:// 資源。像 content-0.js 這種穩定檔名即使在完整擴充功能重載後仍可能提供舊的程式碼。Extension.js 會在開發時加上短雜湊(例如 content-0.abcd1234.js),每次重建都會產生新的 URL 來繞過快取。正式建置則使用乾淨的名稱。在 extension.config.*commands.dev 底下設定 hashContentScripts: false 可以停用它,保留穩定的開發階段檔名。同名的頂層鍵會被忽略。

3) 需要重啟(開發伺服器)

當擴充功能的 entrypoint 引用變更(不僅是模組內容)時,Extension.js 會回報需要重啟的診斷訊息。這能防止你繼續使用過期的依賴圖。 典型的需要重啟情境:
  • Manifest 腳本 entrypoint 清單變更
  • HTML entrypoint 的腳本/樣式引用變更
  • 監看模式下 pages/scripts/ 檔案集合變更(特別是刪除)

行為矩陣

開發階段的 runtime 如何注入

重載外掛會以五個注入步驟為你的建置加裝,然後進行清理:
  1. 從無法承載開發伺服器 runtime 的 content-script chunk 中移除該 runtime。
  2. 在 background 與 content-script entry 上設定重載策略。
  3. 注入 service worker 的腳本重播 shim,讓 /scripts/* 的注入在編輯後重新執行。
  4. 注入 bridge producer,讓 background 把主控台輸出轉送到控制通道。
  5. 注入 bridge relay,讓 content-script 的主控台輸出抵達同一個通道。
之後會有一個清理步驟管理 hot/。熱更新 chunk 是從擴充功能來源上的磁碟取得的,所以過期的世代會在最終產物中累積。Extension.js 會保留目前世代與前一個世代(供進行中的請求使用),並在每次編譯後刪除其餘的。 整條流程僅限開發階段。在正式建置中,以及當你傳入 --no-reload 時,它不會做任何事。

重新載入 manifest 外的腳本與 HTML

pages/scripts/ 採用與 manifest 宣告資產相同的重新載入策略。
  • 既有的模組更新可以使用熱更新路徑。
  • Entrypoint 集合變更(新增/刪除或引用圖變更)可能需要重啟。
範例:
Extension.js 會把 /pages/scripts 資料夾辨識為可熱重載的位置,並把 每個 entry 視為可以獨立重載的頁面或腳本。
/scripts/* 中以 chrome.scripting.executeScript 動態注入的腳本,在編輯時會被 重播。當你修改 /scripts/ 下的檔案時,Extension.js 會在同一個分頁重新執行相同的注入, 並先卸載前一次的掛載——所以動態注入的腳本可以即時更新,效果就像宣告式的 content_scripts 一樣,而不會留下過期的 DOM 直到你手動重新觸發。這是一項僅限開發階段 的便利設計。

最佳實務

  • 在進行中的開發階段保持 entrypoint 引用穩定,以最大化 HMR。
  • manifest.json 與語系編輯批次進行,避免反覆觸發整個擴充功能重載。
  • pages/scripts/ 放置 manifest 之外的資產,當檔案集合或 entry 連線變更時再重啟。
  • 把需要重啟的診斷視為刻意的安全檢查,而不是短暫的警告。

下一步