解鎖 Chrome 擴充功能訊息的結構化複製功能

Justin Lulejian
Justin Lulejian

發布日期:2026 年 4 月 13 日

傳統上,不同擴充功能元件 (背景指令碼、內容指令碼、快顯視窗) 之間的通訊都依賴 JSON 序列化。JSON 雖然可靠,但也有一些限制。

我們很高興宣布,從 Chrome 148 開始,擴充功能開發人員可以選擇使用結構化複製演算法進行訊息序列化,而非 JSON!完成這項現代化作業後,您就能在擴充功能環境之間傳送更複雜的資料類型,不必手動進行序列化作業。

為什麼要使用結構化複製?

JSON 序列化 (透過底層的 JSON.stringify) 可正常運作,但處理新式 JavaScript 型別時,有時需要開發人員費盡心思。

以下是開發擴充功能時可能遇到的具體範例:

// Sending a Map with JSON serialization
const myMap = new Map([['id', 123]]);

// Arrives as {} on the other side!
chrome.runtime.sendMessage(myMap);

// Workaround: Convert Map to an Array of entries before sending
const message = Array.from(myMap.entries());
chrome.runtime.sendMessage(message);

// On the receiving side:
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  const receivedMap = new Map(message);
});

您可能需要解決的其他 JSON 失敗情況包括 SetBigIntNaNInfinityDateError 物件。

使用結構化複製序列化後,您現在可以傳送各種物件,這些物件先前難以或無法透過擴充功能訊息傳輸。舉例來說,現在可以直接傳送 Map 物件:

// Sending a Map with Structured Clone
const myMap = new Map([['id', 123]]);

// Arrives as a Map on the other side!
chrome.runtime.sendMessage(myMap);

// On the receiving side:
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  // message is already a Map instance!
  console.log(message.get('id')); // 123
});

支援更多類型

結構化複製支援各種其他類型,例如 FileBlob

如何加入計劃

為確保回溯相容性,並避免現有擴充功能中斷,這項功能為選用功能。只要在 manifest.json 中新增單一鍵,即可為擴充功能全域啟用這項功能:

{
  "name": "My Extension",
  "version": "1.0",
  "manifest_version": 3,
  "message_serialization": "structured_clone"
}

如果省略這項屬性,或使用低於 148 的 Chrome 版本,瀏覽器會預設採用擴充功能的現行 JSON 實作方式。

我們支援結構化複製演算法,讓擴充功能訊息 API 更符合標準網頁平台功能 (類似於 Web Worker 和 iframe 通訊中使用的 postMessage),提供更靈活且強大的功能。

互通性和注意事項

雖然我們的結構化複製序列化實作支援的類型比 JSON 多,但您應留意實作方式的幾個架構假設和不相容性。

不支援的類型

我們的實作方式不支援共用物件 (例如 SharedArrayBuffer) 和轉移物件 (例如 ArrayBuffer)。SharedArrayBuffer 會無法序列化或還原序列化 (視情況而定),且嘗試傳送 Uint8Array 等可轉移物件時,系統會改為傳送副本。

擴充功能之間的通訊

我們強制執行相符的序列化格式,確保資料完整性。序列化格式不符的擴充功能無法透過 runtime.sendMessageruntime.connect 直接通訊。舉例來說,如果擴充功能 A 使用 JSON 序列化,並嘗試透過結構化複製功能傳送訊息給擴充功能 B,訊息將無法傳送,且通訊埠會關閉 (反之亦然)。

網頁通訊

使用 externally_connectable 的網頁會自動配合目標擴充功能的序列化格式。如果擴充功能使用結構化複製,透過 runtime API 傳送訊息的網頁環境會自動使用結構化複製 (反之亦然)。也就是說,網站和擴充功能必須同步處理預期的序列化格式,才能避免發生序列化錯誤。

原生訊息傳遞

原生訊息傳輸管道一律會強制執行 JSON 序列化。 嘗試將僅限結構化複製的型別 (例如 BigInt) 傳送至原生主機時,系統會在訊息離開擴充功能環境前失敗。

toJSON() 方法

如果您使用具有自訂 toJSON() 方法的類別或物件執行自訂序列化 (例如在傳送物件前移除密碼來清除資料),請注意,結構化複製會忽略 toJSON()。直接複製屬性值。如果您依賴 toJSON() 進行自訂序列化,可能需要先手動處理一些事項,才能傳送資料。例如:

class User {
  constructor(name, password) {
    this.name = name;
    this.password = password;
  }

  // This will be ignored by structured clone!
  toJSON() {
    return { name: this.name };
  }
}

const user = new User("Alice", "secret123");

// JSON -> {"name":"Alice"}
// Structured Clone -> { name: "Alice", password: "secret123" }

JSON 序列化是否會淘汰?

不需要。在可預見的未來,Chrome 會持續支援這兩種序列化格式。

提供意見

我們希望這項新功能有助於您開發擴充功能,打造更順暢、更強大的工作流程。

雖然我們已建立測試套件,用來驗證結構化複製實作的功能,但網頁平台有大量物件。歡迎試用這項新功能,並回報遇到的任何錯誤或極端情況!你的意見有助於我們為整個社群改善實作方式。