ส่วนขยายของ 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 อีกต่อไป ตอนนี้แต่ละแท็บจะจัดเก็บหน้าเว็บหลายหน้าและหน้าเว็บจะเปลี่ยนสถานะไปมาแทนที่จะทำลายและสร้างใหม่

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

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

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

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

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 จะเปลี่ยนแปลงเมื่อหน้าที่แสดงผลล่วงหน้ากลายเป็นหน้าเว็บที่ใช้งานอยู่

เมื่อหน้าเว็บเปลี่ยนจาก Back-Forward Cache หรือการแสดงผลล่วงหน้าไปเป็นสถานะใช้งานอยู่ จะมีเหตุการณ์เพิ่มเติมอีก 3 เหตุการณ์ (แต่มี DocumentLifecyle เป็น "active")

onBeforeNavigate
onCommitted
onCompleted

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

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