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

Dave Tapuska
Dave Tapuska

TL;DR: Extensions API ได้รับการอัปเดตให้รองรับ Back-Forward Cache ซึ่งโหลดการนำทางล่วงหน้า โปรดดูรายละเอียดด้านล่าง

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

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

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

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

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

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

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

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

สิ่งที่เปลี่ยนแปลงไปสำหรับนักพัฒนาส่วนขยาย

FrameId == 0

ใน Chromium เราจะเรียกเฟรมที่อยู่บนสุด/เฟรมหลักว่าเป็นเฟรมด้านนอกสุด

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

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

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

เหตุการณ์การนําทางในเว็บ

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

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

เราได้เพิ่มประเภท DocumentLifecycle ลงใน API ส่วนขยายจำนวนหนึ่งที่ frameId เคยให้บริการก่อนหน้านี้ หากมีประเภท DocumentLifecycle อยู่ในเหตุการณ์ (เช่น onCommitted) ค่าของประเภทดังกล่าวจะเป็นสถานะที่สร้างเหตุการณ์ คุณค้นหาข้อมูลจากเมธอด WebNavigation getFrame() และ getAllFrames() ได้เสมอ แต่เราขอแนะนำให้ใช้ค่าจากเหตุการณ์เสมอ หากคุณใช้วิธีการใดวิธีหนึ่ง โปรดทราบว่าสถานะของเฟรมอาจเปลี่ยนแปลงระหว่างเวลาที่สร้างเหตุการณ์และเวลาที่แก้ไขการสัญญาว่าจะแสดงผลโดยทั้ง 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 และพิจารณาว่าเฟรมใดเป็นเฟรมด้านนอกสุดที่ใช้งานอยู่ได้ ตัวอย่างเช่น js tab.documentLifecycle == “active” && frameType == “outermost_frame”

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

ดังที่กล่าวไว้ข้างต้น เฟรมจะโฮสต์เอกสารและเฟรมอาจนำทางไปยังเอกสารใหม่ แต่ frameId จะไม่เปลี่ยนแปลง ซึ่งจะสร้างปัญหาเมื่อคุณได้รับเหตุการณ์ที่มีเพียง frameId เท่านั้น หากคุณค้นหา URL ของเฟรม 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