ส่วนขยายของ Chrome: การขยาย API เพื่อรองรับการนำทางแบบทันที

Dave Tapuska
Dave Tapuska

TL;DR: Extensions API ได้รับการอัปเดตให้รองรับแคชย้อนหลัง/ไปข้างหน้า รวมถึงการโหลดการไปยังส่วนต่างๆ ล่วงหน้า โปรดดูรายละเอียดด้านล่าง

Chrome พยายามทําให้การนำทางรวดเร็ว เทคโนโลยีการนําทางทันที เช่น Back-Forward Cache (มีให้ใช้งานบนเดสก์ท็อปใน Chrome 96) และกฎการคาดคะเน (มีให้ใช้งานใน Chrome 103) ช่วยปรับปรุงทั้งประสบการณ์การย้อนกลับและเดินหน้า ในโพสต์นี้ เราจะพูดถึงการอัปเดตที่เราทำกับ API ของส่วนขยายเบราว์เซอร์เพื่อรองรับเวิร์กโฟลว์ใหม่เหล่านี้

ทำความเข้าใจประเภทของหน้า

ก่อนที่จะมี Back-Forward Cache และการแสดงผลล่วงหน้า แท็บแต่ละแท็บจะมีหน้าเว็บที่ใช้งานอยู่เพียงหน้าเดียว ตัวเลือกนี้แสดงอยู่เสมอ หากผู้ใช้กลับไปที่หน้าก่อนหน้า ระบบจะทำลายหน้าเว็บที่ใช้งานอยู่ (หน้า B) และสร้างหน้าก่อนหน้าในประวัติขึ้นมาใหม่ทั้งหมด (หน้า A) ส่วนขยายไม่จําเป็นต้องกังวลว่าหน้าเว็บอยู่ในช่วงใดของวงจรเนื่องจากมีเพียงหน้าเดียวสําหรับแท็บหนึ่งๆ นั่นคือสถานะ "ใช้งานอยู่/แสดงอยู่"

การนำหน้าเว็บที่ใช้งานอยู่ออก
การลบหน้าที่ใช้งานอยู่

เมื่อใช้ Back-Forward Cache และการแสดงผลล่วงหน้า แท็บและหน้าเว็บจะไม่มีความสัมพันธ์แบบ 1:1 อีกต่อไป ตอนนี้แต่ละแท็บจะจัดเก็บหน้าเว็บหลายหน้าและหน้าเว็บจะเปลี่ยนสถานะไปมาแทนที่จะทำลายและสร้างใหม่

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

ประเภทหน้าเว็บ
ประเภทหน้าเว็บ

โปรดทราบว่าแท็บหนึ่งๆ อาจมีหน้าเว็บที่แสดงผลล่วงหน้าหลายหน้า (ไม่ใช่แค่หน้าเดียว) หน้าที่ใช้งานอยู่ (แสดงอยู่) หน้าเดียว และหน้าเว็บที่แคชไว้สำหรับ "ย้อนกลับ/ไปข้างหน้า" หลายหน้า

มีอะไรเปลี่ยนแปลงสำหรับนักพัฒนาส่วนขยายบ้าง

FrameId == 0

ใน Chromium เราเรียกเฟรมบนสุด/เฟรมหลักว่าเฟรมด้านนอกสุด

ผู้เขียนส่วนขยายที่ถือว่า frameId ของเฟรมด้านนอกสุดคือ 0 (แนวทางปฏิบัติแนะนำก่อนหน้านี้) อาจพบปัญหา เนื่องจากตอนนี้แท็บมีเฟรมด้านนอกสุดได้หลายเฟรม (หน้าเว็บที่แสดงผลล่วงหน้าและแคชไว้) การคาดการณ์ว่าแท็บมีเฟรมด้านนอกสุดเพียงเฟรมเดียวจึงไม่ถูกต้อง frameId == 0 จะยังคงแสดงเฟรมด้านนอกสุดของหน้าที่ใช้งานอยู่ แต่เฟรมด้านนอกสุดของหน้าอื่นๆ ในแท็บเดียวกันจะไม่เป็น 0 เราได้เพิ่มช่องใหม่ frameType เพื่อแก้ไขปัญหานี้ ดูส่วน"ฉันจะรู้ได้อย่างไรว่าเฟรมเป็นเฟรมด้านนอกสุดหรือไม่" ของโพสต์นี้

วงจรชีวิตของเฟรมเทียบกับเอกสาร

แนวคิดอีกอย่างที่ทำให้เกิดปัญหากับส่วนขยายคือวงจรชีวิตของเฟรม เฟรมโฮสต์เอกสาร (ซึ่งเชื่อมโยงกับ URL ที่คอมมิต) เอกสารอาจเปลี่ยนแปลงได้ (เช่น โดยการไปยังส่วนต่างๆ) แต่ frameId จะไม่เปลี่ยนแปลง ดังนั้นจึงเชื่อมโยงสิ่งที่เกิดขึ้นในเอกสารหนึ่งๆ กับ frameId เพียงอย่างเดียวได้ยาก เราขอแนะนำแนวคิดของ documentId ซึ่งเป็นตัวระบุที่ไม่ซ้ำกันสำหรับเอกสารแต่ละรายการ หากมีการไปยังส่วนต่างๆ ของเฟรมและเปิดเอกสารใหม่ ตัวระบุจะเปลี่ยนไป ช่องนี้มีประโยชน์ในการระบุเวลาที่หน้าเว็บเปลี่ยนสถานะวงจร (ระหว่างการแสดงผลก่อนการโหลด/ใช้งานอยู่/แคชไว้) เนื่องจากค่านี้ยังคงเดิม

เหตุการณ์การไปยังส่วนต่างๆ ของเว็บ

เหตุการณ์ในเนมสเปซ chrome.webNavigation สามารถทริกเกอร์หลายครั้งในหน้าเดียวกันโดยขึ้นอยู่กับวงจรของเหตุการณ์ ดูส่วน"ฉันจะทราบได้อย่างไรว่าหน้าเว็บอยู่ในวงจรใด" และ"ฉันจะทราบได้อย่างไรว่าหน้าเว็บมีการเปลี่ยนแปลงเมื่อใด"

ฉันจะทราบได้อย่างไรว่าหน้าเว็บอยู่ในวงจรใด

เราได้เพิ่มประเภท DocumentLifecycle ลงใน API ของส่วนขยายหลายรายการที่เคยมี frameId ให้บริการก่อนหน้านี้ หากมีประเภท DocumentLifecycle ในเหตุการณ์ (เช่น onCommitted) ค่าของประเภทนี้คือสถานะที่ระบบสร้างเหตุการณ์ คุณสามารถค้นหาข้อมูลจากเมธอด WebNavigation getFrame() และ getAllFrames() ได้ทุกเมื่อ แต่การใช้ค่าจากเหตุการณ์เป็นวิธีที่แนะนำเสมอ หากคุณใช้วิธีใดวิธีหนึ่ง โปรดทราบว่าสถานะของเฟรมอาจเปลี่ยนแปลงระหว่างเวลาที่สร้างเหตุการณ์กับเวลาที่ Promise ของทั้ง 2 วิธีได้รับการแก้ไข

DocumentLifecycle มีค่าดังต่อไปนี้

  • "prerender" : ไม่ได้แสดงต่อผู้ใช้ในขณะนี้ แต่กําลังเตรียมที่จะแสดงต่อผู้ใช้
  • "active": แสดงต่อผู้ใช้อยู่ในขณะนี้
  • "cached": จัดเก็บไว้ในแคชย้อนกลับ/ไปข้างหน้า
  • "pending_deletion": กำลังทำลายเอกสาร

ฉันจะพิจารณาได้อย่างไรว่าเฟรมเป็นเฟรมด้านนอกสุดหรือไม่

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

ด้วยเหตุนี้ เราจึงได้เปิดตัวประเภทใหม่ที่เรียกว่า FrameType เพื่อให้คุณระบุได้ง่ายขึ้นว่าเฟรมนั้นเป็นเฟรมด้านนอกสุดจริงหรือไม่ FrameType มีค่าต่อไปนี้

  • "outermost_frame": มักเรียกว่าเฟรมบนสุด โปรดทราบว่ามีรายการเหล่านี้หลายรายการ ตัวอย่างเช่น หากคุณมีหน้าเว็บที่ผ่านการจัดการแสดงผลล่วงหน้าและแคชไว้ หน้าเว็บแต่ละหน้าจะมีเฟรมด้านนอกสุดซึ่งอาจเรียกว่าเฟรมบนสุด
  • "fenced_frame": สงวนไว้สำหรับการใช้งานในอนาคต
  • "sub_frame": โดยทั่วไปคือ iframe

เรารวม DocumentLifecycle เข้ากับ FrameType และระบุว่าเฟรมเป็นเฟรมด้านนอกสุดที่ใช้งานอยู่หรือไม่ เช่น tab.documentLifecycle === “active” && frameType === “outermost_frame”

ฉันจะแก้ปัญหาเกี่ยวกับเวลาการใช้งานของเฟรมได้อย่างไร

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

ในการแก้ปัญหานี้ เราจึงได้เปิดตัว documentId (และ parentDocumentId) ตอนนี้เมธอด webNavigation.getFrame() จะทำให้ frameId เป็นตัวเลือกได้หากระบุ documentId documentId จะเปลี่ยนแปลงทุกครั้งที่มีการไปยังเฟรมอื่น

ฉันจะกำหนดเวลาการเปลี่ยนหน้าเว็บได้อย่างไร

มีสัญญาณที่ชัดเจนในการระบุว่าหน้าเว็บเปลี่ยนสถานะเมื่อใด

มาดูเหตุการณ์ WebNavigation

สําหรับการนําทางครั้งแรกของหน้าใดก็ตาม คุณจะเห็นเหตุการณ์ 4 รายการตามลําดับที่ระบุไว้ด้านล่าง โปรดทราบว่าเหตุการณ์ทั้ง 4 รายการนี้อาจเกิดขึ้นโดยมีสถานะ DocumentLifecycle เป็น "prerender" หรือ "active"

onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted

ดังที่แสดงในแผนภาพด้านล่าง ซึ่งแสดงให้เห็นว่า documentId เปลี่ยนเป็น "xyz" เมื่อหน้าเว็บที่แสดงผลล่วงหน้ากลายเป็นหน้าเว็บที่ใช้งานอยู่

documentId จะเปลี่ยนแปลงเมื่อหน้าที่แสดงผลล่วงหน้ากลายเป็นหน้าที่ใช้งานอยู่
documentId จะเปลี่ยนแปลงเมื่อหน้าที่แสดงผลล่วงหน้ากลายเป็นหน้าเว็บที่ใช้งานอยู่

เมื่อหน้าเว็บเปลี่ยนจากแคชย้อนกลับ/ไปข้างหน้าหรือการแสดงผลล่วงหน้าเป็นสถานะใช้งาน จะมีเหตุการณ์อีก 3 รายการ (แต่ DocumentLifecyle จะเปลี่ยนเป็น "active")

onBeforeNavigate
onCommitted
onCompleted

documentId จะยังคงเหมือนเดิมกับในเหตุการณ์เดิม ดังที่แสดงด้านบนเมื่อ documentId == xyz เปิดใช้งาน โปรดทราบว่าเหตุการณ์การนําทางเดียวกันจะเริ่มต้นขึ้น ยกเว้นเหตุการณ์ onDOMContentLoaded เนื่องจากหน้าเว็บโหลดไปแล้ว

หากมีความคิดเห็นหรือข้อสงสัย โปรดสอบถามในแชทกลุ่ม chromium-extensions