你來到這頁是因為在 Vite 8 上執行
vite build 出現 [crx:manifest-post] Content script fileName is undefined 嗎?在遷移前,請先參考專門的修正頁的解法。哪些會改、哪些不變
**不變的部分:**你的 React/Vue/Svelte 元件、Tailwind 設定、測試、chrome.* API 呼叫。
會變的部分:
vite.config.ts+@crxjs/vite-plugin變成extension.config.js(或完全不需要設定)。manifest.config.ts(TypeScript 模組)變成純manifest.json,搭配瀏覽器前綴鍵。vite/vite build腳本變成extension dev/extension build。- Extension.js 的 dev 取代 Vite dev server,內建瀏覽器啟動、設定檔管理與各目標的重新載入。
步驟 1:安裝 Extension.js
步驟 2:轉換 manifest
CRXJS 使用 TypeScript 模組:manifest.config.ts
manifest.json,並參考實體檔案:
manifest.json
- manifest 中的副檔名仍是
.ts/.tsx。Extension.js 會在建置期編譯它們。 - 如果你把目錄扁平化,可以省略
src/前綴。Extension.js 會遵從你在 manifest 中宣告的路徑。 - 對於瀏覽器專屬的值,請使用前綴鍵(
firefox:browser_specific_settings),而不是為每個建置寫一份 manifest。
步驟 3:更新 package.json 腳本
把這個:步驟 4:移除 vite.config.ts
如果你的vite.config.ts 只是為了串接 CRXJS,請直接刪除。如果它還有其他 plugin,請把對應功能移到 extension.config.js,或到 Rspack 設定 做進階的打包工具客製。
步驟 5:處理 HMR 差異
CRXJS 的 HMR 透過 Vite WebSocket 推送更新。Extension.js 使用重新載入與 HMR 中說明的另一套模型:- Popup、options、devtools 頁面:HMR。
- Content script:定向重新載入。
- 背景 service worker:完整重啟。
import.meta.hot 在 content script 中執行邏輯,請用一般模組程式碼取代那些分支。Extension.js 會在你的原始碼之外處理重新載入的協調。
步驟 6:跨瀏覽器輸出
CRXJS 鎖定 Chromium。要同時輸出 Firefox:dist/chrome 與 dist/firefox,各自帶有瀏覽器正確的 manifest,以及可上架 Chrome Web Store 與 addons.mozilla.org 的 .zip 壓縮檔。詳見跨瀏覽器相容性。
步驟 7:驗證
chrome.*,而你希望同一份原始碼在 Firefox 上也能執行而不用修改,請加上 --polyfill。
常見地雷
- service worker 的
import陳述句: 當背景進入點使用 ESM 語法時,Extension.js 會自動設定type: "module"。CRXJS 也是這樣做。不必額外處理。 web_accessible_resources的型別: Manifest V3 使用[{resources, matches}]區塊。兩個框架都會輸出正確結構;直接照搬現有項目即可。- 帶 hash 的資產路徑: Extension.js 在
dist/<browser>下使用穩定路徑。如果你的程式碼硬寫了 Vite 風格的 hash 檔名,請改用 manifest 相對路徑。

