Chrome 拡張機能のメッセージングの構造化されたクローン作成を有効にする

Justin Lulejian
Justin Lulejian

公開日: 2026 年 4 月 22 日

さまざまな拡張機能コンポーネント(バックグラウンド スクリプト、コンテンツ スクリプト、ポップアップ)間の通信は、従来 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 に 1 つのキーを追加することで、拡張機能に対してグローバルに有効にできます。

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

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

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

相互運用性と注意点

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

サポートされていないタイプ

SharedArrayBuffer などの共有オブジェクトや、ArrayBuffer などのオブジェクトの転送は、この実装では対象外です。SharedArrayBuffer はシリアル化または逆シリアル化に失敗し(状況によって異なります)、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 は、当面の間、両方のシリアル化形式をサポートする予定です。

フィードバックを共有

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

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