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"
}

省略した場合、または Chrome のバージョンが 148 より前の場合は、ブラウザは拡張機能の現在の JSON ベースの実装をデフォルトで使用します。

構造化クローン アルゴリズムをサポートすることで、拡張機能メッセージング API を標準のウェブ プラットフォーム機能(ウェブワーカーや iframe 通信で使用される postMessage と同様)に近づけ、柔軟性と機能性を高めます。

相互運用性と注意点

構造化クローン シリアル化の実装では、JSON よりも多くの型がサポートされていますが、実装にはいくつかのアーキテクチャ上の前提条件と非互換性があることに注意してください。

サポートされていない型

実装では、 SharedArrayBuffer などの共有オブジェクトや、オブジェクト などの転送はサポートされていません。ArrayBufferSharedArrayBuffer は(状況に応じて)シリアル化または逆シリアル化に失敗し、Uint8Array などの転送可能なオブジェクトを送信しようとすると、代わりにコピーが送信されます。

拡張機能間の通信

データの完全性を確保するため、シリアル化形式の一致を強制します。シリアル化形式が一致しない拡張機能は、runtime.sendMessage または runtime.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 は、当面の間、両方のシリアル化形式をサポートする予定です。

フィードバックを共有

この新機能により、拡張機能開発のワークフローがよりスムーズで強力になることを願っています。

構造化クローン実装の機能を検証するためのテストスイートを作成しましたが、ウェブ プラットフォームにはさまざまなオブジェクトがあります。この新機能をお試しいただき、 バグやエッジケースが見つかった場合はご報告 ください。皆様からのフィードバックは、コミュニティ全体の実装の改善に役立ちます。