跳轉到主要內容
Plasmo 是基於 Parcel 的瀏覽器擴充功能框架,採用檔案慣例的路由方式。它的發布節奏已放緩,工具鏈相對於現代打包工具也漸顯陳舊,這也是許多團隊重新評估的原因。本指南會將典型的 Plasmo 專案遷移到 Extension.js,且不需要改寫你的 UI 程式碼。

哪些會變、哪些不變

維持不變: 你的 React 元件、Tailwind 設定、測試、chrome.* API 呼叫,以及 @plasmohq/storage(如果你有用 — 它是 chrome.storage 的包裝,在這裡運作方式相同)。 會改變:
  • 檔案慣例的進入點(popup.tsxcontents/*.ts)變成真正的 manifest.json 中明確的條目。
  • package.json 中的 manifest 欄位移到 manifest.json
  • plasmo dev / plasmo build / plasmo package 變成 extension dev / extension build --zip
  • PLASMO_PUBLIC_* 環境變數變成 EXTENSION_PUBLIC_*

步驟 1:安裝 Extension.js

npm install extension@latest --save-dev
npm uninstall plasmo

步驟 2:撰寫 manifest

Plasmo 會從 package.json 加上檔案慣例產生 manifest。Extension.js 則把 manifest.json 當作事實來源。逐條轉換每個慣例:
Plasmo 慣例manifest.json 條目
popup.tsxsrc/popup.tsx"action": {"default_popup": "popup/index.html"}
options.tsx"options_ui": {"page": "options/index.html"}
newtab.tsx"chrome_url_overrides": {"newtab": "newtab/index.html"}
background.ts"background": {"service_worker": "background.ts"}
contents/inline.ts 帶 CS 設定"content_scripts": [{...}] 條目
package.json 中的 manifest 欄位直接合併到 manifest.json
HTML 進入點是純 HTML 檔案,用來載入你的 React 元件。一個 popup 看起來像這樣:
popup/index.html
<!doctype html>
<html>
  <body>
    <div id="root"></div>
    <script src="./index.tsx" type="module"></script>
  </body>
</html>
無論在 manifest 或 script 標籤中,副檔名都保留 .ts/.tsx。Extension.js 會在建置時編譯它們。

步驟 3:轉換 content scripts

Plasmo 從匯出的 PlasmoCSConfig 讀取 match:
contents/inline.tsx
import type { PlasmoCSConfig } from "plasmo";

export const config: PlasmoCSConfig = {
  matches: ["https://example.com/*"],
};
在 Extension.js 中,match 寫在 manifest 中,檔案則是一般模組:
manifest.json
{
  "content_scripts": [
    {
      "matches": ["https://example.com/*"],
      "js": ["content/inline.tsx"]
    }
  ]
}
如果你用過 Plasmo 的 CSUI(具備 getRootContainer 與 anchor 的 content script UI),請改用一般的 DOM 程式碼掛載元件:建立一個容器元素,將它附加到你原本錨定的位置,然後渲染到其中。完整模式請見 Content scripts,包括以 shadow DOM 隔離樣式的方式。

步驟 4:環境變數與訊息傳遞

  • .env 檔案與程式碼中的 PLASMO_PUBLIC_* 改名為 EXTENSION_PUBLIC_*。參見環境變數
  • @plasmohq/storage 可以原封不動繼續使用。
  • @plasmohq/messaging 依賴 Plasmo 的 background/messages/* 建置慣例。請以標準的 chrome.runtime.onMessage 監聽器在 background script 中取代處理函式。參見訊息傳遞

步驟 5:更新 package.json 腳本

{
  "scripts": {
    "dev": "extension dev",
    "build": "extension build",
    "start": "extension start"
  }
}
Plasmo 使用 --target=firefox-mv2 的地方,Extension.js 直接以瀏覽器作為目標:
extension build --browser=chrome,firefox --zip
你會得到 dist/chromedist/firefox,附帶各瀏覽器正確的 manifest,以及可上傳到 Chrome Web Store 與 addons.mozilla.org 的 .zip 壓縮檔。

步驟 6:驗證

extension dev --browser=chrome
檢查 popup、options、content scripts 與 background 的行為,再以 --browser=firefox 在 Firefox 上跑相同的驗證。若你的程式碼呼叫 chrome.* 並希望同一份程式碼可在 Firefox 上執行,請使用 --polyfill

常見陷阱

  • assets/ 中的圖示: Plasmo 會從 assets/icon.png 自動產生各種尺寸的圖示。Extension.js 使用 manifest 中 "icons" 所宣告的內容;請自行匯出所需的尺寸。參見 Icons
  • ~ import 別名: Plasmo 將 ~ 別名指向專案根目錄。請在 tsconfig.json 的 paths 中設定它,或改用相對路徑 import。參見 Path resolution
  • Storage hooks: @plasmohq/storage/hookuseStorage 可原封不動使用;它只依賴 React 與 chrome.storage

延伸閱讀