ปลดล็อก Structured Clone สำหรับการรับส่งข้อความของส่วนขยาย Chrome

Justin Lulejian
Justin Lulejian

เผยแพร่: 22 เมษายน 2026

การสื่อสารระหว่างคอมโพเนนต์ส่วนขยายต่างๆ (สคริปต์พื้นหลัง สคริปต์เนื้อหา ป๊อปอัป) มักจะอาศัยการซีเรียลไลซ์ 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 ล้มเหลวซึ่งคุณอาจต้องใช้การแก้ปัญหาชั่วคราว ได้แก่ ออบเจ็กต์ Set, BigInt, NaN และ Infinity, Date และ Error

การใช้การซีเรียลไลซ์การโคลนที่มีโครงสร้างหมายความว่าตอนนี้คุณสามารถส่งออบเจ็กต์ต่างๆ ที่ก่อนหน้านี้ส่งผ่านการรับส่งข้อความของส่วนขยายได้ยากหรือส่งไม่ได้ เช่น ตอนนี้การส่งออบเจ็กต์ 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
});

ประเภทที่รองรับเพิ่มเติม

การโคลนที่มีโครงสร้างรองรับประเภทอื่นๆ มากมาย เช่น File และ Blob

วิธีเลือกเข้าร่วม

ฟีเจอร์นี้เป็นแบบเลือกใช้เพื่อให้มั่นใจว่าสามารถใช้งานร่วมกับเวอร์ชันก่อนหน้าได้และป้องกันไม่ให้ส่วนขยายที่มีอยู่ใช้งานไม่ได้ คุณเปิดใช้ฟีเจอร์นี้ทั่วโลกสำหรับส่วนขยายได้โดยเพิ่มคีย์เดียวลงใน manifest.json ดังนี้

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

หากไม่มี หรือใช้ Chrome เวอร์ชันต่ำกว่า 148 เบราว์เซอร์จะใช้การติดตั้งใช้งานตาม JSON ปัจจุบันสำหรับส่วนขยายเป็นค่าเริ่มต้น

การรองรับอัลกอริทึมการโคลนที่มีโครงสร้างช่วยให้เราสามารถปรับ API การรับส่งข้อความของส่วนขยายให้สอดคล้องกับความสามารถของแพลตฟอร์มเว็บมาตรฐานได้มากขึ้น (คล้ายกับ postMessage ที่ใช้ในการสื่อสารของ Web Worker และ iframe) ซึ่งจะช่วยให้คุณมีความยืดหยุ่นและมีประสิทธิภาพมากขึ้น

ความสามารถในการทำงานร่วมกันและข้อควรระวัง

แม้ว่าการใช้งานการซีเรียลไลซ์การโคลนที่มีโครงสร้างจะรองรับประเภทต่างๆ มากกว่า JSON แต่ก็มีข้อสันนิษฐานด้านสถาปัตยกรรมและความไม่เข้ากันกับการใช้งานที่คุณควรทราบ

ประเภทที่ไม่รองรับ

การติดตั้งใช้งานของเราไม่รองรับออบเจ็กต์ที่แชร์ เช่น SharedArrayBuffer และการโอน ออบเจ็กต์ เช่น ArrayBuffer SharedArrayBuffer จะไม่สามารถซีเรียลไลซ์หรือดีซีเรียลไลซ์ (ขึ้นอยู่กับ สถานการณ์) และการพยายามส่งออบเจ็กต์ที่โอนได้ เช่น Uint8Array จะ ส่งสำเนาแทน

การสื่อสารจากส่วนขยายหนึ่งไปยังอีกส่วนขยายหนึ่ง

เราบังคับใช้รูปแบบการทำให้เป็นอนุกรมที่ตรงกันเพื่อให้มั่นใจว่าข้อมูลมีความสมบูรณ์ ส่วนขยายที่มีรูปแบบการเรียงอันดับไม่ตรงกันจะสื่อสารผ่าน runtime.sendMessage หรือ runtime.connect โดยตรงไม่ได้ เช่น หากส่วนขยาย A ใช้การซีเรียลไลซ์ JSON และพยายามส่งข้อความไปยังส่วนขยาย B โดยใช้การโคลนที่มีโครงสร้าง ระบบจะไม่สามารถส่งข้อความและพอร์ตจะปิด (และในทางกลับกัน)

การสื่อสารในหน้าเว็บ

หน้าเว็บที่ใช้ externally_connectable จะปรับให้เข้ากับรูปแบบการซีเรียลไลซ์ของส่วนขยายเป้าหมายโดยอัตโนมัติ หากส่วนขยายใช้การโคลนแบบมีโครงสร้าง บริบทเว็บที่ส่งข้อความโดยใช้ runtime API จะใช้การโคลนแบบมีโครงสร้าง (และในทางกลับกัน) โดยอัตโนมัติ ซึ่งหมายความว่าเว็บไซต์และส่วนขยายต้องซิงค์กัน ในรูปแบบการทำให้เป็นอนุกรมที่คาดไว้เพื่อป้องกันข้อผิดพลาดในการทำให้เป็นอนุกรม

การรับส่งข้อความแบบเดิม

ช่องทางการรับส่งข้อความดั้งเดิมจะยังคงบังคับให้ใช้การซีเรียลไลซ์ JSON เสมอ การพยายามส่งประเภทที่โคลนแบบมีโครงสร้างเท่านั้น (เช่น BigInt) ไปยังโฮสต์ดั้งเดิม จะล้มเหลวก่อนที่ข้อความจะออกจากบริบทของส่วนขยาย

เมธอด toJSON()

หากคุณใช้คลาสหรือออบเจ็กต์ที่มีtoJSON()เมธอดที่กำหนดเองเพื่อทำการซีเรียลไลเซชันที่กำหนดเอง (เช่น การล้างข้อมูลโดยการนำรหัสผ่านออกก่อนส่งออบเจ็กต์) โปรดทราบว่า Structured Clone จะไม่สนใจ 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" }

Is JSON serialization going away?

ไม่เอาด้วยหรอก Chrome มุ่งมั่นที่จะรองรับรูปแบบการเรียงอันดับทั้ง 2 รูปแบบในอนาคตอันใกล้

แชร์ความคิดเห็น

เราหวังว่าความสามารถใหม่นี้จะช่วยให้เวิร์กโฟลว์การพัฒนาส่วนขยายของคุณราบรื่นและมีประสิทธิภาพมากขึ้น

แม้ว่าเราจะสร้างชุดทดสอบเพื่อตรวจสอบความถูกต้องของฟังก์ชันการทำงานสำหรับการติดตั้งใช้งานการโคลนที่มีโครงสร้าง แต่แพลตฟอร์มเว็บก็มีออบเจ็กต์ที่หลากหลายมาก ลองใช้ฟีเจอร์ใหม่นี้และรายงานข้อบกพร่องหรือกรณีที่พบ ความคิดเห็นของคุณจะช่วยเราปรับปรุง การใช้งานสำหรับชุมชนทั้งหมด