แคชย้อนหลัง

Back/Forward Cache (หรือ bfcache) คือการเพิ่มประสิทธิภาพเบราว์เซอร์ที่ช่วยให้มีการนำทางกลับและไปข้างหน้าแบบทันที เครื่องมือนี้ช่วยปรับปรุงประสบการณ์การท่องเว็บได้อย่างมาก โดยเฉพาะอย่างยิ่งสำหรับผู้ใช้เครือข่ายหรืออุปกรณ์ที่ช้า

หน้านี้จะสรุปวิธีเพิ่มประสิทธิภาพหน้าเว็บสำหรับ bfcache ในทุกเบราว์เซอร์

ความเข้ากันได้กับเบราว์เซอร์

bfcache รองรับทั้ง Firefox และ Safari มาหลายปีแล้วทั้งในเดสก์ท็อปและอุปกรณ์เคลื่อนที่

ตั้งแต่เวอร์ชัน 86 เป็นต้นไป Chrome ได้เปิดใช้ bfcache สำหรับการนำทางข้ามเว็บไซต์ใน Android สำหรับผู้ใช้เพียงไม่กี่เปอร์เซ็นต์ ในรุ่นต่อๆ ไป จะมีการเปิดตัวการสนับสนุนเพิ่มเติมอย่างช้าๆ ตั้งแต่เวอร์ชัน 96 เป็นต้นไป จะมีการเปิดใช้ bfcache สำหรับผู้ใช้ Chrome ทุกคนในเดสก์ท็อปและอุปกรณ์เคลื่อนที่

ข้อมูลเบื้องต้นเกี่ยวกับ bfcache

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

วิดีโอต่อไปนี้แสดงให้เห็นว่า bfcache ช่วยเร่งความเร็วในการไปยังส่วนต่างๆ ได้มากน้อยเพียงใด

การใช้ bfcache ทำให้หน้าเว็บโหลดเร็วขึ้นมากในระหว่างการนำทางย้อนกลับและไปข้างหน้า

ข้อมูลการใช้งาน Chrome แสดงให้เห็นว่า 1 ใน 10 การนำทางบนเดสก์ท็อปและ 1 ใน 5 การนำทางบนอุปกรณ์เคลื่อนที่ จะย้อนกลับหรือไปข้างหน้า ด้วยเหตุนี้ bfcache มีศักยภาพในการ ประหยัดเวลาและปริมาณการใช้อินเทอร์เน็ตได้อย่างมาก

วิธีการทำงานของ "แคช"

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

อย่างไรก็ตาม การสร้างสแนปชอตของหน้าในหน่วยความจำจะมีความซับซ้อนบางประการเนื่องจากต้องเก็บรักษาโค้ดที่อยู่ระหว่างดำเนินการจึงจะดีที่สุด ตัวอย่างเช่น คุณจะจัดการการเรียก setTimeout() เมื่อถึงระยะหมดเวลาขณะที่หน้าเว็บอยู่ใน bfcache ได้อย่างไร

คำตอบคือเบราว์เซอร์จะหยุดตัวจับเวลาที่รอดำเนินการหรือสัญญาที่ยังไม่ได้แก้ไขสำหรับหน้าเว็บใน bfcache รวมถึงงานเกือบทั้งหมดที่รอดำเนินการในคิวงาน JavaScript และทำงานการประมวลผลต่อหากมีการคืนค่าหน้าจาก bfcache

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

ดูรายละเอียดเพิ่มเติมเกี่ยวกับวิธีที่การใช้ API ส่งผลต่อการมีสิทธิ์ bfcache ของหน้าเว็บได้ที่เพิ่มประสิทธิภาพหน้าเว็บสำหรับ bfcache

แอป bfcache และแอปหน้าเว็บเดียว (SPA)

เนื่องจาก bfcache ใช้งานได้กับการนำทางที่จัดการโดยเบราว์เซอร์ จึงไม่ใช้กับ "การนำทางแบบนุ่มนวล" ภายในแอปแบบหน้าเว็บเดียว (SPA) ไม่ได้ อย่างไรก็ตาม bfcache ยังช่วยได้ เมื่อคุณออกจากบ้านและกลับมาใช้ SPA

API สำหรับสังเกต bfcache

แม้ว่า bfcache จะเป็นการเพิ่มประสิทธิภาพที่เบราว์เซอร์ทำโดยอัตโนมัติ แต่นักพัฒนาซอฟต์แวร์ยังคงจำเป็นต้องทราบว่าเมื่อใดที่จะเกิด Conversion ขึ้น เพื่อที่จะสามารถเพิ่มประสิทธิภาพให้กับหน้าเว็บของตน และปรับเมตริกหรือการวัดประสิทธิภาพได้ตามความเหมาะสม

เหตุการณ์หลักที่ใช้สังเกต bfcache คือเหตุการณ์การเปลี่ยนหน้าเว็บ pageshow และ pagehide ซึ่งเบราว์เซอร์ส่วนใหญ่รองรับ

นอกจากนี้ ระบบจะส่งเหตุการณ์วงจรการใช้งานหน้าเว็บที่ใหม่กว่า freeze และ resume เมื่อหน้าเว็บเข้าหรือออกจาก bfcache รวมถึงในสถานการณ์อื่นๆ เช่น เมื่อแท็บพื้นหลังค้างเพื่อลดการใช้งาน CPU เหตุการณ์เหล่านี้ใช้ได้เฉพาะในเบราว์เซอร์แบบ Chromium

สังเกตเมื่อมีการคืนค่าหน้าจาก bfcache

เหตุการณ์ pageshow จะเริ่มทำงานหลังจากเหตุการณ์ load เมื่อหน้าเว็บกำลังโหลดเป็นครั้งแรกและทุกครั้งที่มีการคืนค่าหน้าจาก bfcache เหตุการณ์ pageshow มีพร็อพเพอร์ตี้ persisted ซึ่งมีค่าเป็น true หากหน้าเว็บได้รับการกู้คืนจาก bfcache หรือ false ในกรณีอื่นๆ คุณใช้พร็อพเพอร์ตี้ persisted เพื่อแยกการโหลดหน้าเว็บปกติออกจากการคืนค่า bfcache ได้ เช่น

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    console.log('This page was restored from the bfcache.');
  } else {
    console.log('This page was loaded normally.');
  }
});

ในเบราว์เซอร์ที่รองรับ Page Lifecycle API เหตุการณ์ resume จะเริ่มทำงานเมื่อคืนค่าหน้าเว็บจาก bfcache (ก่อนเหตุการณ์ pageshow ทันที) และเมื่อผู้ใช้กลับไปอยู่ในแท็บพื้นหลังที่ตรึงใหม่ หากต้องการอัปเดตสถานะของหน้าเว็บหลังจากที่หน้าหยุดค้าง (ซึ่งรวมถึงหน้าใน bfcache) ให้ใช้เหตุการณ์ resume แต่หากต้องการวัดอัตรา Hit ของ bfcache ของเว็บไซต์ คุณจะต้องใช้เหตุการณ์ pageshow ในบางกรณี คุณอาจต้องใช้ทั้ง 2 อย่าง

โปรดดูรายละเอียดเกี่ยวกับแนวทางปฏิบัติแนะนําสําหรับการวัด bfcache ที่ bfcache ส่งผลต่อข้อมูลวิเคราะห์และการวัดประสิทธิภาพอย่างไร

สังเกตเมื่อหน้าเว็บป้อน bfcache

เหตุการณ์ pagehide จะเริ่มทำงานเมื่อหน้าเว็บยกเลิกการโหลดหรือเมื่อเบราว์เซอร์พยายามใส่หน้านั้นลงใน bfcache

เหตุการณ์ pagehide มีพร็อพเพอร์ตี้ persisted ด้วย หากเป็น false ก็มั่นใจได้เลยว่าหน้านั้นไม่ได้กำลังป้อน bfcache แต่ persisted การใช้ true ไม่ได้รับประกันว่าจะมีการแคชหน้าเว็บ ซึ่งหมายความว่าเบราว์เซอร์intendsให้แคชหน้าเว็บไว้ แต่อาจมีปัจจัยอื่นๆ ที่ทำให้แคชไม่ได้

window.addEventListener('pagehide', (event) => {
  if (event.persisted) {
    console.log('This page *might* be entering the bfcache.');
  } else {
    console.log('This page will unload normally and be discarded.');
  }
});

ในทำนองเดียวกัน เหตุการณ์ freeze จะเริ่มทำงานทันทีหลังจากเหตุการณ์ pagehide หาก persisted คือ true แต่นั่นหมายความว่าเบราว์เซอร์intendsให้แคชหน้าเว็บดังกล่าวเท่านั้น แต่อาจยังคงต้องทิ้งโดเมนดังกล่าวด้วยเหตุผลหลายประการซึ่งได้อธิบายไว้ภายหลัง

เพิ่มประสิทธิภาพหน้าเว็บสำหรับ bfcache

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

ใช้ pagehide แทน unload

วิธีที่สำคัญที่สุดในการเพิ่มประสิทธิภาพสำหรับ bfcache ในเบราว์เซอร์ทั้งหมดคือการไม่ใช้ Listener เหตุการณ์ unload ฟัง pagehide แทน เนื่องจากระบบจะเริ่มทํางานทั้งเมื่อหน้าเว็บเข้าสู่ bfcache และทุกครั้งที่ unload เริ่มทำงาน

unload เป็นฟีเจอร์ที่เก่ากว่า ซึ่งเดิมออกแบบมาเพื่อทริกเกอร์ทุกครั้งที่ผู้ใช้ออกจากหน้าเว็บ แต่ไม่เป็นเช่นนั้นแล้ว แต่หน้าเว็บจำนวนมากยังคงทำงานโดยสันนิษฐานว่าเบราว์เซอร์ใช้ unload ด้วยวิธีนี้ และหลังจากทริกเกอร์ unload แล้ว หน้าเว็บที่ยกเลิกการโหลดจะหยุดที่มีอยู่ ซึ่งอาจทำให้ bfcache ใช้งานไม่ได้หากเบราว์เซอร์พยายามแคชหน้าที่ไม่ได้โหลด

ในเดสก์ท็อป Chrome และ Firefox ทำให้หน้าเว็บที่มี Listener unload ไม่มีสิทธิ์ใช้ฟีเจอร์ bfcache ซึ่งช่วยลดความเสี่ยงแต่ก็ทำให้ไม่มีการแคชหน้าจำนวนมากและจึงโหลดซ้ำได้ช้าลงมาก Safari พยายามแคชบางหน้าที่มี Listener เหตุการณ์ unload แต่เพื่อลดความเสียหายที่อาจเกิดขึ้น จึงไม่เรียกใช้เหตุการณ์ unload เมื่อผู้ใช้ออกจากหน้าไป ซึ่งทำให้ Listener ของ unload ไม่น่าเชื่อถือ

ในอุปกรณ์เคลื่อนที่ Chrome และ Safari จะพยายามแคชหน้าเว็บด้วย Listener เหตุการณ์ unload เพราะความไม่เสถียรของ unload ในอุปกรณ์เคลื่อนที่จึงทำให้ความเสี่ยงในการเกิดความเสียหายลดลง Firefox บนอุปกรณ์เคลื่อนที่จะถือว่าหน้าที่ใช้ unload ไม่มีสิทธิ์ใช้ฟีเจอร์ bfcache ยกเว้นใน iOS ที่เบราว์เซอร์ทุกชนิดต้องใช้เครื่องมือแสดงผล WebKit เพื่อให้มีลักษณะการทำงานเหมือน Safari

หากต้องการตรวจสอบว่า JavaScript ในหน้าเว็บใช้ unload หรือไม่ เราขอแนะนำให้ใช้การตรวจสอบ no-unload-listeners ใน Lighthouse

ดูข้อมูลเกี่ยวกับแผนของ Chrome ในการเลิกใช้งาน unload ได้ที่การเลิกใช้งานเหตุการณ์ยกเลิกการโหลด

ใช้นโยบายสิทธิ์เพื่อป้องกันไม่ให้มีการใช้ตัวแฮนเดิลการยกเลิกการโหลดในหน้าเว็บ

สคริปต์และส่วนขยายของบุคคลที่สามบางรายการสามารถเพิ่มตัวแฮนเดิลการยกเลิกการโหลดลงในหน้าเว็บ ซึ่งทำให้เว็บไซต์ช้าลงเนื่องจากไม่มีสิทธิ์ใช้ bfcache หากต้องการป้องกันปัญหานี้ใน Chrome 115 ขึ้นไป ให้ใช้นโยบายสิทธิ์

Permission-Policy: unload()

เพิ่ม Listener beforeunload อย่างมีเงื่อนไข

เหตุการณ์ beforeunload ไม่ได้ทำให้หน้าเว็บไม่มีสิทธิ์ใช้ bfcache อย่างไรก็ตาม วิธีนี้ไม่น่าเชื่อถือ เราจึงขอแนะนำให้ใช้เมื่อจำเป็นเท่านั้น

ตัวอย่างกรณีการใช้งาน beforeunload คือการเตือนผู้ใช้ว่าการเปลี่ยนแปลงที่ไม่ได้บันทึกไว้จะสูญหายหากออกจากหน้าไป ในกรณีนี้ เราขอแนะนำให้เพิ่ม Listener beforeunload เฉพาะเมื่อผู้ใช้มีการเปลี่ยนแปลงที่ไม่ได้บันทึก จากนั้นจึงนำออกทันทีหลังจากที่บันทึกการเปลี่ยนแปลงที่ยังไม่ได้บันทึก ดังที่แสดงในโค้ดต่อไปนี้

function beforeUnloadListener(event) {
  event.preventDefault();
  return event.returnValue = 'Are you sure you want to exit?';
};

// A function that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges(() => {
  window.addEventListener('beforeunload', beforeUnloadListener);
});

// A function that invokes a callback when the page's unsaved changes are resolved.
onAllChangesSaved(() => {
  window.removeEventListener('beforeunload', beforeUnloadListener);
});

ลดการใช้ Cache-Control: no-store

Cache-Control: no-store เป็นเว็บเซิร์ฟเวอร์ส่วนหัว HTTP ที่ตั้งค่าการตอบกลับที่สั่งเบราว์เซอร์ไม่ให้เก็บการตอบกลับไว้ในแคช HTTP ใดๆ ได้ ซึ่งใช้สำหรับทรัพยากรที่มีข้อมูลผู้ใช้ที่ละเอียดอ่อน เช่น หน้าที่ต้องเข้าสู่ระบบก่อน

แม้ว่า bfcache จะไม่ใช่แคช HTTP แต่เบราว์เซอร์ได้ยกเว้นหน้าเว็บจาก bfcache ในอดีตไว้เมื่อตั้งค่า Cache-Control: no-store ในทรัพยากรของหน้า (แต่ไม่ใช่ในทรัพยากรย่อยใดๆ) Chrome กำลังพยายาม เปลี่ยนแปลงลักษณะการทำงานนี้ ขณะที่รักษาความเป็นส่วนตัวของผู้ใช้ แต่โดยค่าเริ่มต้น หน้าเว็บที่ใช้ Cache-Control: no-store จะไม่มีสิทธิ์ใช้ bfcache

หากต้องการเพิ่มประสิทธิภาพ bfcache ให้ใช้ Cache-Control: no-store เฉพาะในหน้าที่มีข้อมูลที่ละเอียดอ่อนซึ่งต้องไม่แคชไว้

สำหรับหน้าที่ต้องการแสดงเนื้อหาล่าสุดเสมอ แต่ไม่รวมข้อมูลที่ละเอียดอ่อน ให้ใช้ Cache-Control: no-cache หรือ Cache-Control: max-age=0 การดำเนินการนี้จะบอกให้เบราว์เซอร์ตรวจสอบเนื้อหาอีกครั้งก่อนแสดงผล และไม่ส่งผลกระทบต่อการมีสิทธิ์ bfcache ของหน้าเว็บ เนื่องจากการกู้คืนหน้าเว็บจาก bfcache ไม่เกี่ยวข้องกับแคช HTTP

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

อัปเดตข้อมูลเก่าหรือข้อมูลที่ละเอียดอ่อนหลังจากคืนค่า bfcache

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

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

หากไม่ต้องการให้เกิดเหตุการณ์เช่นนี้ ให้อัปเดตหน้าเว็บเสมอหลังจากเหตุการณ์ pageshow หาก event.persisted คือ true

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // Do any checks and updates to the page
  }
});

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

window.addEventListener('pageshow', (event) => {
  if (event.persisted && !document.cookie.match(/my-cookie)) {
    // Force a reload if the user has logged out.
    location.reload();
  }
});

การคืนค่าโฆษณาและ bfcache

คุณคงอยากหลีกเลี่ยงการใช้ bfcache เพื่อให้หน้าเว็บของคุณแสดงโฆษณาชุดใหม่ได้ในการนำทางกลับหรือไปข้างหน้าแต่ละครั้ง อย่างไรก็ตาม การทำเช่นนี้เป็นผลเสียต่อประสิทธิภาพของเว็บไซต์ และไม่ได้เพิ่มการมีส่วนร่วมกับโฆษณาอย่างสม่ำเสมอ ตัวอย่างเช่น ผู้ใช้อาจตั้งใจที่จะกลับไปยังหน้าเว็บเพื่อคลิกโฆษณา แต่หากโหลดหน้าเว็บซ้ำแทนที่จะคืนค่าจาก bfcache โฆษณาดังกล่าวอาจแสดงเป็นโฆษณาอื่น เราขอแนะนำให้ใช้การทดสอบ A/B เพื่อระบุกลยุทธ์ที่ดีที่สุดสำหรับหน้าเว็บ

สําหรับเว็บไซต์ที่ต้องการรีเฟรชโฆษณาในการกู้คืน bfcache คุณจะรีเฟรชได้เฉพาะโฆษณาในเหตุการณ์ pageshow เมื่อ event.persisted เป็น true โดยไม่ส่งผลต่อประสิทธิภาพของหน้าเว็บ ดังเช่นในตัวอย่างแท็กการเผยแพร่ของ Google หากต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับแนวทางปฏิบัติแนะนำสำหรับเว็บไซต์ โปรดสอบถามผู้ให้บริการโฆษณา

หลีกเลี่ยงการอ้างอิง window.opener

ในเบราว์เซอร์รุ่นเก่า หากหน้าเว็บเปิดโดยใช้ window.open() จากลิงก์ target=_blank โดยไม่ระบุ rel="noopener" หน้าที่เปิดอยู่จะมีการอ้างอิงไปยังออบเจ็กต์หน้าต่างของหน้าที่เปิด

นอกจากก่อให้เกิดความเสี่ยงด้านความปลอดภัยแล้ว คุณไม่สามารถใส่หน้าที่มีการอ้างอิง window.opener ที่ไม่เป็นค่าว่างลงใน bfcache ได้อย่างปลอดภัย เนื่องจากอาจทำให้หน้าใดก็ตามที่พยายามเข้าถึงหน้านั้นเสียหาย

หากต้องการหลีกเลี่ยงความเสี่ยงเหล่านี้ ให้ใช้ rel="noopener" เพื่อป้องกันการสร้างข้อมูลอ้างอิง window.opener นี่เป็นลักษณะการทำงานเริ่มต้นในเบราว์เซอร์รุ่นใหม่ทั้งหมด หากเว็บไซต์ต้องการเปิดหน้าต่างและควบคุมโดยใช้ window.postMessage() หรือโดยการอ้างอิงออบเจ็กต์หน้าต่างโดยตรง ทั้งหน้าต่างที่เปิดอยู่และหน้าต่างที่เปิดอยู่จะไม่มีสิทธิ์ใช้ bfcache

ปิดการเชื่อมต่อที่เปิดอยู่ก่อนที่ผู้ใช้จะออกจากหน้า

ตามที่ได้กล่าวไว้ก่อนหน้านี้ เมื่อใส่หน้าเว็บลงใน bfcache แล้ว งาน JavaScript ที่กำหนดเวลาไว้ทั้งหมดจะหยุดไว้ชั่วคราวและกลับมาทำงานอีกครั้งเมื่อหน้าเว็บถูกนำออกจากแคช

หากงาน JavaScript ที่กำหนดเวลาไว้เหล่านี้เข้าถึงเฉพาะ DOM API หรือ API อื่นๆ ที่แยกต่างหากไปยังหน้าปัจจุบัน การหยุดงานเหล่านี้ชั่วคราวในขณะที่ผู้ใช้มองไม่เห็นหน้าจะไม่ทำให้เกิดปัญหา

อย่างไรก็ตาม หากงานเหล่านี้เชื่อมต่อกับ API ที่เข้าถึงได้จากหน้าอื่นๆ ในต้นทางเดียวกัน (เช่น IndexedDB, Web Locks และ WebSockets) การหยุดงานเหล่านั้นชั่วคราวอาจทำลายหน้าเว็บเหล่านั้นด้วยการป้องกันไม่ให้โค้ดในหน้าเหล่านั้นทำงาน

ดังนั้น บางเบราว์เซอร์จะไม่พยายามใส่หน้าใน bfcache หากมีรายการใดรายการหนึ่งต่อไปนี้

หากหน้าเว็บใช้ API เหล่านี้ เราขอแนะนำอย่างยิ่งให้ปิดการเชื่อมต่อ แล้วยกเลิกหรือยกเลิกการเชื่อมต่อผู้สังเกตการณ์ในระหว่างเหตุการณ์ pagehide หรือ freeze ซึ่งทำให้เบราว์เซอร์แคชหน้าได้อย่างปลอดภัยโดยไม่ต้องเสี่ยงที่จะกระทบต่อแท็บอื่นๆ ที่เปิดอยู่ จากนั้นหากหน้าเว็บได้รับการกู้คืนจาก bfcache คุณจะสามารถเปิดหรือเชื่อมต่อกับ API เหล่านั้นอีกครั้งในระหว่างเหตุการณ์ pageshow หรือ resume

ตัวอย่างต่อไปนี้แสดงวิธีตรวจสอบว่าหน้าที่ใช้ IndexedDB มีสิทธิ์สำหรับ bfcache โดยการปิดการเชื่อมต่อแบบเปิดในตัว Listener เหตุการณ์ pagehide

let dbPromise;
function openDB() {
  if (!dbPromise) {
    dbPromise = new Promise((resolve, reject) => {
      const req = indexedDB.open('my-db', 1);
      req.onupgradeneeded = () => req.result.createObjectStore('keyval');
      req.onerror = () => reject(req.error);
      req.onsuccess = () => resolve(req.result);
    });
  }
  return dbPromise;
}

// Close the connection to the database when the user leaves.
window.addEventListener('pagehide', () => {
  if (dbPromise) {
    dbPromise.then(db => db.close());
    dbPromise = null;
  }
});

// Open the connection when the page is loaded or restored from bfcache.
window.addEventListener('pageshow', () => openDB());

ทดสอบว่าหน้าเว็บของคุณสามารถแคชได้

เครื่องมือสำหรับนักพัฒนาเว็บใน Chrome ช่วยคุณทดสอบหน้าเว็บเพื่อให้มั่นใจว่าหน้าได้รับการเพิ่มประสิทธิภาพสำหรับ bfcache แล้ว รวมถึงระบุปัญหาที่อาจทำให้หน้าเหล่านั้นไม่มีสิทธิ์

วิธีทดสอบหน้า

  1. ไปที่หน้าเว็บใน Chrome
  2. ในเครื่องมือสำหรับนักพัฒนาเว็บ ให้ไปที่แอปพลิเคชัน > แคชย้อนหลัง
  3. คลิกปุ่ม Run Test จากนั้นเครื่องมือสำหรับนักพัฒนาเว็บจะพยายามออกและย้อนกลับ เพื่อดูว่าจะคืนค่าหน้าจาก bfcache ได้ไหม
แผง Back-Forward Cache ในเครื่องมือสำหรับนักพัฒนาเว็บ
แผงBack-Forward Cache ในเครื่องมือสำหรับนักพัฒนาเว็บ

หากการทดสอบสำเร็จ แผงจะรายงานว่า "กู้คืนจาก Back-Forward Cache" หากไม่สำเร็จ แผงจะแสดงสาเหตุ ดูรายการเหตุผลทั้งหมดได้ที่รายการเหตุผลที่ไม่ได้กู้คืนสําหรับ Chromium

หากเหตุผลเป็นสิ่งที่คุณจัดการได้ในฐานะนักพัฒนาซอฟต์แวร์ แผงจะทําเครื่องหมายว่าดําเนินการได้

การรายงานเครื่องมือสำหรับนักพัฒนาเว็บไม่สามารถกู้คืนหน้าจาก bfcache ได้
การทดสอบ bfcache ไม่สำเร็จซึ่งมีผลลัพธ์ที่นำไปดำเนินการได้

ในรูปภาพนี้ การใช้ Listener เหตุการณ์ unload จะทำให้หน้าเว็บไม่มีสิทธิ์ใช้ bfcache คุณสามารถแก้ไขได้โดยเปลี่ยนจาก unload ไปใช้ pagehide

ควรทำ
window.addEventListener('pagehide', ...);
ไม่ควรทำ
window.addEventListener('unload', ...);

Lighthouse 10.0 ยังเพิ่มการตรวจสอบ bfcache ซึ่งทำการทดสอบในลักษณะเดียวกัน ดูข้อมูลเพิ่มเติมได้ในเอกสารของการตรวจสอบ bfcache

bfcache ส่งผลต่อข้อมูลวิเคราะห์และการวัดประสิทธิภาพอย่างไร

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

อันที่จริง คุณอาจรายงานการดูหน้าเว็บจากเบราว์เซอร์อื่นๆ ที่ใช้ bfcache ได้ต่ำกว่าความเป็นจริง เนื่องจากไลบรารี Analytics ที่ได้รับความนิยมส่วนใหญ่ไม่ได้ติดตามการคืนค่า bfcache เป็นการดูหน้าเว็บใหม่

หากต้องการรวมการคืนค่า bfcache ลงในจำนวนการดูหน้าเว็บ ให้ตั้งค่า Listener สำหรับเหตุการณ์ pageshow และตรวจสอบพร็อพเพอร์ตี้ persisted

ตัวอย่างต่อไปนี้แสดงวิธีดําเนินการดังกล่าวด้วย Google Analytics เครื่องมือวิเคราะห์อื่นๆ ที่น่าจะใช้ตรรกะคล้ายกัน

// Send a pageview when the page is first loaded.
gtag('event', 'page_view');

window.addEventListener('pageshow', (event) => {
  // Send another pageview if the page is restored from bfcache.
  if (event.persisted) {
    gtag('event', 'page_view');
  }
});

วัดอัตรา Hit ของ bfcache

หากต้องการระบุหน้าเว็บที่ยังไม่ได้ใช้ bfcache ให้วัดประเภทการไปยังส่วนต่างๆ ของการโหลดหน้าเว็บดังนี้

// Send a navigation_type when the page is first loaded.
gtag('event', 'page_view', {
   'navigation_type': performance.getEntriesByType('navigation')[0].type;
});

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // Send another pageview if the page is restored from bfcache.
    gtag('event', 'page_view', {
      'navigation_type': 'back_forward_cache';
    });
  }
});

คำนวณอัตราส่วน Hit ของ bfcache โดยใช้จำนวนสำหรับการนำทาง back_forward และการนำทาง back_forward_cache

เหตุผลที่การย้อนกลับหรือไปข้างหน้าอาจใช้ bfcache ไม่ได้ มีดังนี้

  • การปิดและรีสตาร์ทเบราว์เซอร์
  • การทำซ้ำแท็บ
  • การปิดและกู้คืนแท็บ

ในบางกรณี เบราว์เซอร์อาจเก็บประเภทการนําทางเดิมไว้และแสดงประเภท back_forward แม้ว่ารายการเหล่านี้จะไม่ใช่การนําทางแบบย้อนกลับหรือไปข้างหน้า แม้ว่าจะรายงานประเภทการนำทางอย่างถูกต้อง ระบบก็จะทิ้ง bfcache เป็นระยะๆ เพื่อประหยัดหน่วยความจำ

ด้วยเหตุนี้ เจ้าของเว็บไซต์จึงไม่คาดว่าจะมีอัตรา Hit ของ bfcache 100% สําหรับการไปยังส่วนต่างๆ ของ back_forward ทั้งหมด อย่างไรก็ตาม การวัดอัตราส่วนจะช่วยระบุหน้าที่ป้องกันการใช้ bfcache ได้

ทีม Chrome กำลังพัฒนา NotRestoredReasons API เพื่อแสดงเหตุผลที่หน้าเว็บไม่ใช้ bfcache เพื่อให้นักพัฒนาซอฟต์แวร์ปรับปรุงอัตราการค้นพบ bfcache ได้

การวัดประสิทธิภาพ

bfcache อาจส่งผลเสียต่อเมตริกประสิทธิภาพที่รวบรวมในช่องโดยเฉพาะเมตริกที่วัดเวลาในการโหลดหน้าเว็บ

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

คุณสามารถจัดการกับปัญหานี้ได้หลายวิธี วิธีแรกคือการใส่คำอธิบายประกอบในเมตริกการโหลดหน้าเว็บทั้งหมดด้วยประเภทการนำทางที่เกี่ยวข้อง ได้แก่ navigate, reload, back_forward หรือ prerender วิธีนี้ช่วยให้คุณตรวจสอบประสิทธิภาพภายในประเภทการนําทางเหล่านี้ต่อไปได้ แม้ว่าการกระจายโดยรวมจะคลาดเคลื่อนไป เราขอแนะนำให้ใช้วิธีนี้กับเมตริกการโหลดหน้าเว็บที่ไม่เน้นผู้ใช้ เช่น Time to First Byte (TTFB)

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

ผลกระทบต่อ Core Web Vitals

Core Web Vitals วัดประสบการณ์ของผู้ใช้ของหน้าเว็บในมิติข้อมูลต่างๆ (ความเร็วในการโหลด การโต้ตอบ ความเสถียรของภาพ) เมตริก Core Web Vitals ของคุณจำเป็นต้องสะท้อนให้เห็นถึงข้อเท็จจริงที่ว่าผู้ใช้จะคืนค่า bfcache เป็นการนำทางที่เร็วกว่าการโหลดหน้าเว็บเริ่มต้น

เครื่องมือที่รวบรวมและรายงานเกี่ยวกับเมตริก Core Web Vitals เช่น รายงานประสบการณ์ของผู้ใช้ Chrome จะถือว่าการคืนค่า bfcache เป็นการเข้าชมหน้าเว็บแยกต่างหากในชุดข้อมูล และแม้ว่าจะไม่มี API ประสิทธิภาพเว็บสำหรับการวัดเมตริกเหล่านี้หลังจากการกู้คืน bfcache โดยเฉพาะแล้ว แต่คุณสามารถประมาณค่าของเมตริกโดยใช้ API ของเว็บที่มีอยู่ได้ ดังนี้

  • สำหรับ Largest Contentful Paint (LCP) ให้ใช้เดลต้าระหว่างการประทับเวลาของเหตุการณ์ pageshow กับการประทับเวลาของเฟรมที่ระบายสีถัดไป เนื่องจากองค์ประกอบทั้งหมดในเฟรมจะได้รับการทาสีพร้อมกัน ในกรณีของการคืนค่า bfcache นั้น LCP และ FCP จะเหมือนกัน
  • สำหรับ Interaction to Next Paint (INP) ให้ใช้ Performance Observer ที่มีอยู่ต่อไป แต่รีเซ็ตค่า CLS ปัจจุบันเป็น 0
  • สำหรับ Cumulative Layout Shift (CLS) ให้ใช้ Performance Observer ที่มีอยู่ต่อไป แต่รีเซ็ตค่า CLS ปัจจุบันเป็น 0

ดูรายละเอียดเพิ่มเติมว่า bfcache ส่งผลต่อเมตริกแต่ละรายการอย่างไรได้ที่หน้าคำแนะนำเมตริกของ Core Web Vitals สำหรับตัวอย่างเฉพาะเกี่ยวกับวิธีใช้เมตริกเหล่านี้ในเวอร์ชัน bfcache อ่านประชาสัมพันธ์การเพิ่มเวอร์ชันลงในไลบรารี JS ของ Web-vitals

แหล่งข้อมูลเพิ่มเติม