การรองรับเบราว์เซอร์
บางครั้งเบราว์เซอร์สมัยใหม่จะระงับหน้าเว็บหรือทิ้งหน้าเว็บไปทั้งหมด ทรัพยากรระบบมีจำกัด ในอนาคต เบราว์เซอร์ต้องการทำสิ่งนี้ เพื่อให้ใช้พลังงานและหน่วยความจำน้อยลง Page Lifecycle API มีฮุกวงจรเพื่อให้หน้าเว็บของคุณสามารถจัดการเบราว์เซอร์เหล่านี้ได้อย่างปลอดภัย แทรกแซงได้โดยไม่ส่งผลกระทบต่อประสบการณ์ของผู้ใช้ ดูที่ API เพื่อ ดูว่าคุณควรนำฟีเจอร์เหล่านี้ไปใช้กับแอปพลิเคชันของคุณไหม
ข้อมูลเบื้องต้น
วงจรแอปพลิเคชันคือวิธีหลักที่ระบบปฏิบัติการสมัยใหม่จัดการ ที่ไม่ซับซ้อน ใน Android, iOS และ Windows เวอร์ชันล่าสุด คุณสามารถเริ่มใช้แอป ถูกหยุดการทำงานได้ตลอดเวลาโดยระบบปฏิบัติการ ทำให้แพลตฟอร์มเหล่านี้สามารถเพิ่มประสิทธิภาพ และ จัดสรรทรัพยากรที่มีประโยชน์ต่อผู้ใช้มากที่สุด
ไม่เคยมีวงจรการใช้งานแบบนั้นบนเว็บเลย และสามารถเก็บแอป จะไม่มีที่สิ้นสุด เมื่อมีหน้าเว็บจำนวนมากทำงานอยู่ ระบบวิกฤติ ทรัพยากรต่างๆ เช่น หน่วยความจํา, CPU, แบตเตอรี่ และเครือข่ายอาจสมัครใช้บริการมากเกินไป ทำให้ผู้ใช้ปลายทางได้รับประสบการณ์ที่ไม่ดี
แม้ว่าแพลตฟอร์มเว็บจะมีเหตุการณ์ที่เกี่ยวข้องกับสถานะของวงจรมาเป็นเวลานานแล้ว
— เช่น load
unload
และ
visibilitychange
— กิจกรรมเหล่านี้อนุญาตให้เฉพาะนักพัฒนาซอฟต์แวร์เท่านั้น
เพื่อตอบสนองต่อการเปลี่ยนแปลงสถานะของวงจรที่เริ่มต้นโดยผู้ใช้ เพื่อให้ใช้งานเว็บได้
เชื่อถือได้บนอุปกรณ์ที่ใช้พลังงานต่ำ (และคำนึงถึงทรัพยากรโดยทั่วไปเกี่ยวกับ
ทุกแพลตฟอร์ม) ที่เบราว์เซอร์ต้องการวิธีเชิงรุกในการเรียกคืนและจัดสรรระบบใหม่
ที่ไม่ซับซ้อน
อันที่จริงแล้ว เบราว์เซอร์ในปัจจุบันได้ใช้มาตรการเชิงรุกเพื่อประหยัดทรัพยากรอยู่แล้ว สำหรับหน้าเว็บในแท็บที่ทำงานอยู่เบื้องหลัง และเบราว์เซอร์ต่างๆ (โดยเฉพาะ Chrome) ต้องการ ให้ทำสิ่งต่างๆ ได้มากขึ้น นั่นก็คือการลดการใช้ทรัพยากรโดยรวม
ปัญหาก็คือนักพัฒนาซอฟต์แวร์ไม่มีทางที่จะเตรียมตัวรับมือ การฝึกฝนที่เริ่มต้นโดยระบบ หรือแม้กระทั่งรู้ว่ากำลังเกิดขึ้น ซึ่งหมายความว่า เบราว์เซอร์จึงต้องระมัดระวังเสมอ หรือมีโอกาสที่จะทำให้หน้าเว็บเสียหาย
Page Lifecycle API พยายามแก้ไขปัญหานี้โดย:
- แนะนำและสร้างมาตรฐานให้กับแนวคิดสถานะของวงจรบนเว็บ
- การกำหนดสถานะใหม่ที่เริ่มต้นโดยระบบซึ่งช่วยให้เบราว์เซอร์สามารถจำกัด ทรัพยากรที่อาจใช้งานโดยแท็บที่ซ่อนอยู่หรือที่ไม่ได้ใช้งาน
- การสร้าง API และเหตุการณ์ใหม่ที่ช่วยให้นักพัฒนาเว็บตอบกลับ การเปลี่ยนแปลงไปยังและจากสถานะที่เริ่มต้นโดยระบบเหล่านี้
โซลูชันนี้มอบความสามารถในการคาดการณ์ที่นักพัฒนาเว็บจะต้องสร้าง แอปพลิเคชันมีความยืดหยุ่นและรองรับการแทรกแซงระบบ และยังช่วยให้เบราว์เซอร์ เพิ่มประสิทธิภาพทรัพยากรระบบในเชิงรุก ซึ่งสุดท้ายแล้วเป็นประโยชน์ต่อผู้ใช้เว็บทุกคน
ส่วนที่เหลือของโพสต์นี้จะแนะนำฟีเจอร์ใหม่เกี่ยวกับวงจรของหน้า และสำรวจว่าความเกี่ยวข้องกับสถานะ ของแพลตฟอร์มเว็บที่มีอยู่ทั้งหมดอย่างไร และกิจกรรม รวมถึงให้คําแนะนําและแนวทางปฏิบัติแนะนําสําหรับประเภท ที่นักพัฒนาควร (และไม่ควร) ทำในแต่ละรัฐ
ภาพรวมสถานะและเหตุการณ์ในวงจรของหน้า
สถานะวงจรทั้งหมดของหน้าเว็บจะแยกกันและแยกจากกัน ซึ่งหมายความว่าหน้าเว็บ สามารถมีสถานะได้ทีละหนึ่งสถานะเท่านั้น และการเปลี่ยนแปลงส่วนใหญ่ต่อสถานะวงจรของหน้าเว็บ โดยทั่วไปจะสามารถสังเกตการณ์ได้ผ่านเหตุการณ์ DOM (ดูข้อยกเว้นในคำแนะนำของนักพัฒนาซอฟต์แวร์สำหรับแต่ละสถานะ)
บางทีวิธีที่ง่ายที่สุดในการอธิบายสถานะของวงจรหน้าเว็บ รวมถึง เหตุการณ์ที่ส่งสัญญาณถึงการเปลี่ยนแปลงระหว่างเหตุการณ์ทั้งสอง ได้แก่ แผนภาพ
รัฐ
ตารางต่อไปนี้อธิบายแต่ละสถานะโดยละเอียด และยังแสดงรายการที่เป็นไปได้ ซึ่งสามารถเกิดขึ้นก่อนและหลัง รวมถึงเหตุการณ์ที่นักพัฒนาซอฟต์แวร์สามารถ ใช้สังเกตการเปลี่ยนแปลง
รัฐ | คำอธิบาย |
---|---|
ใช้งานอยู่ |
หน้าเว็บจะอยู่ในสถานะใช้งานอยู่หากมองเห็นได้และ โฟกัสอินพุต
สถานะก่อนหน้าที่เป็นไปได้มีดังนี้ |
เชิงรับ |
หน้าเว็บจะอยู่ในสถานะพาสซีฟหากมองเห็นได้และ ไม่ได้โฟกัสอินพุต
สถานะก่อนหน้าที่เป็นไปได้มีดังนี้
สถานะถัดไปที่เป็นไปได้มีดังนี้ |
ซ่อนอยู่ |
หน้าเว็บจะอยู่ในสถานะซ่อน หากไม่เห็น (และไม่เห็น ถูกตรึง ทิ้ง หรือสิ้นสุดการใช้งาน)
สถานะก่อนหน้าที่เป็นไปได้มีดังนี้
สถานะถัดไปที่เป็นไปได้มีดังนี้ |
หยุดการทำงาน |
ในสถานะถูกตรึง เบราว์เซอร์จะระงับการดำเนินการ
เพิ่มพื้นที่ว่างได้
งานในส่วนของหน้า
ไว้ในคิวงานจนกว่าหน้าจะเลิกตรึง ซึ่งหมายความว่า
ตัวจับเวลา JavaScript และ Callback ที่ดึงข้อมูลไม่ทำงาน ทำงานอยู่แล้ว
งานต่างๆ ให้เสร็จได้ (ที่สำคัญที่สุดคือ
เบราว์เซอร์ตรึงหน้าเว็บไว้เพื่อประหยัดการใช้ CPU/แบตเตอรี่/ข้อมูล พวกเขา ก็เพราะเป็นวิธีที่จะช่วยให้ การนำทางแบบย้อนหลัง — ไม่จำเป็นต้องใช้หน้าเต็ม โหลดซ้ำ
สถานะก่อนหน้าที่เป็นไปได้มีดังนี้
สถานะถัดไปที่เป็นไปได้มีดังนี้ |
สิ้นสุดการใช้งาน |
เมื่อเริ่มหน้าเว็บจะอยู่ในสถานะถูกยุติ ยกเลิกการโหลดและล้างออกจากหน่วยความจำโดยเบราว์เซอร์ ยังไม่ได้ติดต่อ งานใหม่อาจเริ่มต้นในสถานะนี้ และงานที่อยู่ระหว่างดำเนินการอาจ ตายหากเล่นนานเกินไป
สถานะก่อนหน้าที่เป็นไปได้มีดังนี้
สถานะถัดไปที่เป็นไปได้มีดังนี้ |
ทิ้งแล้ว |
หน้าเว็บจะอยู่ในสถานะยกเลิกเมื่อยกเลิกการโหลดโดย เพื่อประหยัดทรัพยากร ไม่มีงาน การเรียกกลับเหตุการณ์ หรือ JavaScript ทุกประเภทสามารถทำงานในสถานะนี้ได้ เนื่องจากโดยทั่วไปทิ้ง JavaScript เกิดขึ้นภายใต้ข้อจำกัดด้านทรัพยากร ซึ่งมีการเริ่มต้นกระบวนการใหม่ เป็นไปไม่ได้ ในสถานะยกเลิกแล้ว แท็บ (รวมถึงชื่อแท็บและไอคอน Fav) มักแสดงต่อผู้ใช้ แม้ว่าหน้าเว็บนั้นจะหายไปแล้ว
สถานะก่อนหน้าที่เป็นไปได้มีดังนี้
สถานะถัดไปที่เป็นไปได้มีดังนี้ |
กิจกรรม
เบราว์เซอร์จะส่งเหตุการณ์จำนวนมาก แต่มีเพียงไม่กี่เหตุการณ์เท่านั้นที่ส่งสัญญาณ การเปลี่ยนแปลงในสถานะวงจรของหน้า ตารางต่อไปนี้จะสรุปเหตุการณ์ทั้งหมด ที่เกี่ยวข้องกับวงจรและระบุสถานะของสถานะที่อาจเปลี่ยนและมาจาก
ชื่อ | รายละเอียด |
---|---|
focus
|
องค์ประกอบ DOM ได้รับการโฟกัส
หมายเหตุ: เหตุการณ์
สถานะก่อนหน้าที่เป็นไปได้มีดังนี้
สถานะปัจจุบันที่เป็นไปได้มีดังนี้ |
blur
|
องค์ประกอบ DOM สูญเสียโฟกัส
หมายเหตุ: เหตุการณ์
สถานะก่อนหน้าที่เป็นไปได้มีดังนี้
สถานะปัจจุบันที่เป็นไปได้มีดังนี้ |
visibilitychange
|
เอกสาร
ค่า |
วันที่ freeze
*
|
หน้านี้เพิ่งจะถูกตรึง ช่วง งานที่ตรึงได้ในคิวงานของหน้าจะไม่เริ่ม
สถานะก่อนหน้าที่เป็นไปได้มีดังนี้
สถานะปัจจุบันที่เป็นไปได้มีดังนี้ |
วันที่ resume
*
|
เบราว์เซอร์ได้เปิดหน้าเว็บที่ค้างอีกครั้ง
สถานะก่อนหน้าที่เป็นไปได้มีดังนี้
สถานะปัจจุบันที่เป็นไปได้มีดังนี้ |
pageshow
|
กำลังข้ามรายการประวัติเซสชัน ซึ่งอาจเป็นการโหลดหน้าเว็บใหม่หรือหน้าเว็บที่นำมาจาก
back/Forward Cache หากหน้า
มาจากแคชย้อนหลัง
พร็อพเพอร์ตี้
สถานะก่อนหน้าที่เป็นไปได้มีดังนี้ |
pagehide
|
กำลังข้ามผ่านรายการประวัติเซสชัน หากผู้ใช้ไปยังหน้าอื่นและเบราว์เซอร์สามารถเพิ่ม
หน้าปัจจุบันเป็น back/Forward
แคช เพื่อนำมาใช้ใหม่ในภายหลัง พร็อพเพอร์ตี้
สถานะก่อนหน้าที่เป็นไปได้มีดังนี้
สถานะปัจจุบันที่เป็นไปได้มีดังนี้ |
beforeunload
|
ระบบกำลังยกเลิกการโหลดหน้าต่าง เอกสาร และทรัพยากร เอกสารยังมองเห็นได้อยู่และคุณยังยกเลิกกิจกรรมได้ที่ คะแนน
สำคัญ: เหตุการณ์
สถานะก่อนหน้าที่เป็นไปได้มีดังนี้
สถานะปัจจุบันที่เป็นไปได้มีดังนี้ |
unload
|
กำลังยกเลิกการโหลดหน้านี้
คำเตือน:
เราไม่แนะนำให้ใช้เหตุการณ์
สถานะก่อนหน้าที่เป็นไปได้มีดังนี้
สถานะปัจจุบันที่เป็นไปได้มีดังนี้ |
* ระบุเหตุการณ์ใหม่ที่กำหนดโดย Page Lifecycle API
ฟีเจอร์ใหม่ที่เพิ่มเข้ามาใน Chrome 68
แผนภูมิก่อนหน้านี้แสดงสถานะ 2 สถานะเริ่มต้นโดยระบบ ไม่ใช่ เริ่มโดยผู้ใช้: ค้างและยกเลิกแล้ว ดังที่กล่าวไว้ก่อนหน้านี้ เบราว์เซอร์ในปัจจุบันมีการหยุดและทิ้งเป็นบางครั้งอยู่แล้ว แท็บที่ซ่อนอยู่ (ขึ้นอยู่กับการพิจารณาตามที่เห็นสมควร) แต่นักพัฒนาซอฟต์แวร์ไม่มีทางรู้ว่าเมื่อใด สิ่งนี้กำลังเกิดขึ้น
ใน Chrome 68 ตอนนี้นักพัฒนาแอปจะสังเกตเห็นได้เมื่อแท็บที่ซ่อนอยู่ค้างและ
เลิกตรึงโดยการฟัง freeze
และ resume
กิจกรรมในวันที่ document
document.addEventListener('freeze', (event) => {
// The page is now frozen.
});
document.addEventListener('resume', (event) => {
// The page has been unfrozen.
});
จาก Chrome 68 ตอนนี้ออบเจ็กต์ document
มี
wasDiscarded
ใน Chrome บนเดสก์ท็อป (ปัญหานี้กำลังมีการติดตามการสนับสนุนของ Android ในปัญหานี้) เพื่อดูว่าหน้าเว็บถูกทิ้งขณะที่ซ่อนไว้หรือไม่
คุณสามารถตรวจสอบค่าของคุณสมบัตินี้ในการโหลดหน้าเว็บ (หมายเหตุ:
หน้าเว็บที่ทิ้งจะต้องโหลดซ้ำเพื่อนำมาใช้อีกครั้ง)
if (document.wasDiscarded) {
// Page was previously discarded by the browser while in a hidden tab.
}
หากต้องการคำแนะนำเกี่ยวกับสิ่งสำคัญที่ต้องทำในfreeze
และresume
รวมถึงวิธีจัดการและเตรียมพร้อมสำหรับการทิ้งหน้าเว็บ โปรดดู
คำแนะนำจากนักพัฒนาแอปในแต่ละรัฐ
ข้อมูลในส่วนต่อๆ ไปจะแสดงภาพรวมของ คุณสมบัติใหม่นี้ สถานะและเหตุการณ์ของแพลตฟอร์มเว็บที่มีอยู่
วิธีสังเกตสถานะอายุการใช้งานของหน้าเว็บในโค้ด
ในโหมดแอ็กทีฟ พาสซีฟ และซ่อนอยู่ สถานะ สามารถเรียกใช้โค้ด JavaScript ที่กำหนดสถานการณ์ สถานะวงจรของหน้าจาก API ของแพลตฟอร์มเว็บที่มีอยู่
const getState = () => {
if (document.visibilityState === 'hidden') {
return 'hidden';
}
if (document.hasFocus()) {
return 'active';
}
return 'passive';
};
สถานะหยุดนิ่งและสิ้นสุดบน
ในอีกแบบหนึ่ง จะสามารถตรวจพบได้ใน Listener เหตุการณ์ที่เกี่ยวข้องเท่านั้น
(freeze
และ pagehide
) ตามรัฐ
กำลังเปลี่ยนแปลง
วิธีสังเกตการเปลี่ยนแปลงสถานะ
ต่อยอดจากฟังก์ชัน getState()
ที่กำหนดไว้ก่อนหน้านี้ คุณสามารถสังเกตหน้าทั้งหมด
สถานะของวงจรจะเปลี่ยนแปลงตามโค้ดต่อไปนี้
// Stores the initial state using the `getState()` function (defined above).
let state = getState();
// Accepts a next state and, if there's been a state change, logs the
// change to the console. It also updates the `state` value defined above.
const logStateChange = (nextState) => {
const prevState = state;
if (nextState !== prevState) {
console.log(`State change: ${prevState} >>> ${nextState}`);
state = nextState;
}
};
// Options used for all event listeners.
const opts = {capture: true};
// These lifecycle events can all use the same listener to observe state
// changes (they call the `getState()` function to determine the next state).
['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'].forEach((type) => {
window.addEventListener(type, () => logStateChange(getState()), opts);
});
// The next two listeners, on the other hand, can determine the next
// state from the event itself.
window.addEventListener('freeze', () => {
// In the freeze event, the next state is always frozen.
logStateChange('frozen');
}, opts);
window.addEventListener('pagehide', (event) => {
// If the event's persisted property is `true` the page is about
// to enter the back/forward cache, which is also in the frozen state.
// If the event's persisted property is not `true` the page is
// about to be unloaded.
logStateChange(event.persisted ? 'frozen' : 'terminated');
}, opts);
โค้ดนี้ทำหน้าที่ 3 อย่างดังนี้
- ตั้งค่าสถานะเริ่มต้นโดยใช้ฟังก์ชัน
getState()
- กำหนดฟังก์ชันที่ยอมรับสถานะถัดไป และหากมีการเปลี่ยนแปลง จะบันทึกสถานะการเปลี่ยนแปลงไปยังคอนโซล
- การเพิ่ม
การจับภาพ
Listener เหตุการณ์สำหรับเหตุการณ์ในวงจรที่จำเป็นทั้งหมด ซึ่งสุดท้ายแล้วก็จะเป็นการเรียก
logStateChange()
ผ่านในสถานะถัดไป
สิ่งหนึ่งที่ควรทราบเกี่ยวกับโค้ดคือจะมีการเพิ่ม Listener เหตุการณ์ทั้งหมด
ถึง window
ทุกอย่างก็ให้ที่
{capture: true}
ซึ่งอาจเป็นเพราะสาเหตุต่อไปนี้
- เหตุการณ์ในวงจรของหน้าบางเหตุการณ์ไม่ได้มีเป้าหมายเหมือนกัน
pagehide
และpageshow
เริ่มทำงานในwindow
visibilitychange
,freeze
และresume
เริ่มทำงานในdocument
และfocus
และblur
เริ่มทำงานใน เอลิเมนต์ DOM ที่เกี่ยวข้อง - กิจกรรมเหล่านี้ส่วนใหญ่ไม่แสดงเป็นบับเบิล ซึ่งหมายความว่าเพิ่มไม่ได้ Listener เหตุการณ์ที่ไม่ใช่การบันทึกไปยังองค์ประกอบระดับบนที่พบบ่อยและสังเกตทั้งหมด ทั้งหมด
- ระยะการจับภาพจะทำงานก่อนระยะเป้าหมายหรือช่วงลูกโป่ง ดังนั้นการเพิ่ม Listener ในนั้นช่วยให้มั่นใจว่าตนจะทำงานก่อนที่โค้ดอื่นๆ จะยกเลิกได้
คำแนะนำจากนักพัฒนาแอปสำหรับแต่ละรัฐ
ในฐานะนักพัฒนาซอฟต์แวร์ คุณควรทำความเข้าใจสถานะของวงจรการใช้งานหน้าเว็บและ รู้วิธีสังเกตการณ์ในโค้ดเนื่องจากประเภทงานที่คุณควร (และควร ส่วนใหญ่แล้วจะขึ้นอยู่กับสถานะของหน้าเว็บ
ตัวอย่างเช่น การแสดงการแจ้งเตือนชั่วคราวอาจไม่เหมาะสมอย่างชัดเจน ให้กับผู้ใช้หากหน้าเว็บมีสถานะซ่อน ขณะที่ตัวอย่างนี้ ยังมีคำแนะนำอื่นๆ ที่ไม่ชัดเจนซึ่งมีคุณค่า แจกแจง
รัฐ | คำแนะนำสำหรับนักพัฒนาซอฟต์แวร์ |
---|---|
Active |
สถานะใช้งานอยู่เป็นเวลาที่สำคัญที่สุดสำหรับผู้ใช้และด้วยเหตุนี้ ช่วงเวลาที่สำคัญที่สุดที่หน้าเว็บของคุณจะ ตอบสนองต่อข้อมูลจากผู้ใช้ งานที่ไม่ใช้ UI ที่อาจบล็อกเทรดหลักควรลดลำดับความสำคัญลง ถึง ระยะเวลาที่ไม่มีการใช้งานหรือ ให้กับ Web Worker |
Passive |
ในสถานะแพสซีฟ ผู้ใช้ไม่ได้โต้ตอบกับหน้าเว็บ แต่จะยังเห็นได้อยู่ ซึ่งหมายความว่าการอัปเดต UI และภาพเคลื่อนไหว อย่างราบรื่น แต่ช่วงเวลาที่มีการอัปเดตเหล่านี้ไม่สำคัญนัก เมื่อหน้าเว็บเปลี่ยนจากแอ็กทีฟเป็นแพสซีฟ ถึงเวลายืนยันสถานะแอปพลิเคชันที่ไม่ได้บันทึกแล้ว |
เมื่อหน้าเว็บเปลี่ยนจากแฝงเป็นซ่อน เป็นไปได้ว่าผู้ใช้จะไม่โต้ตอบกับแอปอีกจนกว่าจะโหลดใหม่ การเปลี่ยนเป็น "ซ่อน" มักเป็นการเปลี่ยนแปลงสถานะสุดท้ายด้วย
ซึ่งนักพัฒนาซอฟต์แวร์จะสังเกตได้อย่างน่าเชื่อถือ (โดยเฉพาะอย่างยิ่งใน
บนอุปกรณ์เคลื่อนที่ เนื่องจากผู้ใช้สามารถปิดแท็บหรือแอปเบราว์เซอร์ได้ และ
ซึ่งหมายความว่าคุณควรถือว่าสถานะถูกซ่อนเป็นสถานะที่มีแนวโน้มที่จะสิ้นสุด เซสชันของผู้ใช้ กล่าวคือ ให้คงสถานะของแอปพลิเคชันที่ไม่ได้บันทึกไว้ แล้วส่งข้อมูลวิเคราะห์ที่ยังไม่ได้ส่ง นอกจากนี้ คุณควรหยุดทำการอัปเดต UI ด้วย (เนื่องจากจะไม่มีใครเห็นการอัปเดตเหล่านั้น ตามที่ผู้ใช้ไม่ได้) และคุณควรหยุดงานใดๆ ที่ผู้ใช้ไม่ต้องการ ทำงานในพื้นหลัง |
|
Frozen |
ในสถานะค้าง งานที่ตรึงได้ใน คิวงานจะถูกระงับจนกว่าหน้าเว็บจะเลิกตรึง ซึ่งอาจ ไม่เคยเกิดขึ้นเลย (เช่น หากหน้าเว็บถูกยกเลิก) ซึ่งหมายความว่าหน้าเว็บจะเปลี่ยนจากซ่อนเป็นตรึงไว้ คุณจำเป็นต้องหยุดการจับเวลา หรือตัดการเชื่อมต่อที่ หากค้าง อาจส่งผลต่อแท็บอื่นๆ ที่เปิดอยู่ในต้นทางเดียวกัน หรือส่งผลต่อ ความสามารถของเบราว์เซอร์ในการวางหน้าเว็บใน Back-Forward Cache โดยเฉพาะอย่างยิ่ง คุณต้อง
นอกจากนี้ คุณยังควรคงสถานะมุมมองแบบไดนามิกเอาไว้ด้วย (เช่น ตำแหน่งเลื่อน
ในมุมมองรายการแบบไม่สิ้นสุด) เพื่อ
หากหน้าเว็บเปลี่ยนจากค้างกลับไปเป็นซ่อน คุณสามารถเปิดการเชื่อมต่อที่ปิดไปขึ้นมาใหม่ หรือเริ่มโพลใหม่ก็ได้ หยุดเมื่อหน้าเว็บถูกตรึงในตอนแรก |
Terminated |
โดยทั่วไปแล้วคุณไม่ต้องดำเนินการใดๆ เมื่อเปลี่ยนหน้า เป็นสถานะสิ้นสุด เนื่องจากระบบจะยกเลิกการโหลดซึ่งเป็นผลมาจากการดำเนินการของผู้ใช้เสมอ ผ่านสถานะซ่อนก่อนที่จะเข้าสู่สถานะสิ้นสุด สถานะ ซ่อนคือตำแหน่งที่ตรรกะสิ้นสุดเซสชัน (เช่น สถานะของแอปพลิเคชันอย่างต่อเนื่องและการรายงานไปยัง Analytics) ควรเป็น ที่ได้รับ โปรดทราบด้วยว่า (ดังที่ได้กล่าวไว้ในคำแนะนำสำหรับ
สถานะซ่อนอยู่) นักพัฒนาซอฟต์แวร์จะต้องตระหนักถึง
ว่าการเปลี่ยนเป็นสภาวะที่ ถูกยุติ นั้นเชื่อถือได้
ในหลายกรณี (โดยเฉพาะบนอุปกรณ์เคลื่อนที่) ดังนั้นนักพัฒนาซอฟต์แวร์ที่พึ่งพา
เกี่ยวกับเหตุการณ์การสิ้นสุด (เช่น |
Discarded |
นักพัฒนาแอปจะมองไม่เห็นสถานะยกเลิกแล้ว ทุกครั้งที่มีการยกเลิกหน้าเว็บ เนื่องจากโดยทั่วไปหน้าเว็บ ทิ้งภายใต้ข้อจำกัดของทรัพยากร และเลิกตรึงหน้าเพียงเพื่อให้ สคริปต์ในการเรียกใช้เพื่อตอบสนองกับเหตุการณ์ทิ้งนั้นเป็นไปไม่ได้ใน เกือบทุกกรณี ดังนั้น คุณจึงควรเตรียมพร้อมสำหรับความเป็นไปได้ที่จะยกเลิก
เปลี่ยนจากซ่อนเป็นตรึงไว้ คุณก็จะสามารถ
ตอบสนองต่อการกู้คืนหน้าเว็บที่ถูกยกเลิกเมื่อโหลดหน้าเว็บโดย
กำลังตรวจสอบ |
เนื่องจากความน่าเชื่อถือและการเรียงลำดับเหตุการณ์ในวงจรไม่ใช่ มีการใช้งานอย่างสอดคล้องกันในทุกเบราว์เซอร์ วิธีที่ง่ายที่สุดในการทำตามคำแนะนำ ในตารางคือให้ใช้ PageLifecycle.js
API อายุการใช้งานเดิมที่ควรหลีกเลี่ยง
คุณควรหลีกเลี่ยงเหตุการณ์ต่อไปนี้หากเป็นไปได้
เหตุการณ์ยกเลิกการโหลด
นักพัฒนาซอฟต์แวร์จำนวนมากถือว่าเหตุการณ์ unload
เป็นการเรียกกลับที่รับประกันการแสดงผลและใช้เป็น
สัญญาณตอนท้ายเซสชันเพื่อบันทึกสถานะและส่งข้อมูลการวิเคราะห์ แต่การทำเช่นนี้
ไม่น่าเชื่อถืออย่างมาก โดยเฉพาะในอุปกรณ์เคลื่อนที่ เหตุการณ์ unload
ไม่
เริ่มทำงานในสถานการณ์ยกเลิกการโหลดโดยทั่วไปมากมาย รวมถึงการปิดแท็บจากแท็บ
ตัวสลับบนอุปกรณ์เคลื่อนที่หรือปิดแอปเบราว์เซอร์จากตัวสลับแอป
ด้วยเหตุนี้ คุณจึงควรพึ่งพา
visibilitychange
ที่จะระบุเวลาของเซสชัน
สิ้นสุด และพิจารณาสถานะที่ซ่อนอยู่
ช่วงเวลาที่เชื่อถือได้ล่าสุดในการประหยัดแอปและข้อมูลผู้ใช้
นอกจากนี้ ระบบจะแสดงเพียงตัวแฮนเดิลเหตุการณ์ unload
ที่ลงทะเบียนไว้ (ผ่าน
onunload
หรือaddEventListener()
) จะทำให้เบราว์เซอร์ไม่สามารถ
เพื่อวางหน้าเว็บใน back/Forward Cache เพื่อให้เร็วขึ้น
การโหลดแบบย้อนหลังและไปข้างหน้า
ในเบราว์เซอร์สมัยใหม่ทั้งหมด เราขอแนะนำให้ใช้
pagehide
สำหรับตรวจหากรณีที่หน้าเว็บอาจยกเลิกการโหลด (เรียกอีกอย่างว่า
สถานะ สิ้นสุด) แทนที่จะเป็นเหตุการณ์ unload
หากคุณ
ต้องรองรับ Internet Explorer เวอร์ชัน 10 หรือเก่ากว่า คุณควรแสดง
ตรวจหาเหตุการณ์ pagehide
และใช้ unload
เฉพาะเมื่อเบราว์เซอร์ไม่รองรับ
pagehide
:
const terminationEvent = 'onpagehide' in self ? 'pagehide' : 'unload';
window.addEventListener(terminationEvent, (event) => {
// Note: if the browser is able to cache the page, `event.persisted`
// is `true`, and the state is frozen rather than terminated.
});
เหตุการณ์ beforeunload
เหตุการณ์ beforeunload
มีปัญหาที่คล้ายกับเหตุการณ์ unload
ในนั้น
ในอดีต การมีเหตุการณ์ beforeunload
อาจทำให้หน้าเว็บไม่สามารถ
มีสิทธิ์ใช้แคชย้อนหลัง เบราว์เซอร์สมัยใหม่
ไม่มีข้อจำกัดนี้ เพื่อเป็นการป้องกันไว้ก่อน บางเบราว์เซอร์จะไม่เริ่มทำงาน
เหตุการณ์ beforeunload
เมื่อพยายามใส่หน้าลงใน Back-Forward
แคช ซึ่งหมายความว่าเหตุการณ์ไม่น่าเชื่อถือเป็นสัญญาณเมื่อสิ้นสุดเซสชัน
นอกจากนี้บางเบราว์เซอร์ (รวมถึง Chrome)
ต้องมีการโต้ตอบของผู้ใช้ในหน้าเว็บก่อนจึงจะอนุญาตเหตุการณ์ beforeunload
ให้เริ่มการทำงานได้มากขึ้น ส่งผลต่อความเสถียรมากกว่าเดิม
ความแตกต่างอย่างหนึ่งระหว่าง beforeunload
และ unload
คือ
การใช้งานที่ถูกต้องตามกฎหมายของ beforeunload
เช่น เมื่อต้องการเตือนผู้ใช้
การเปลี่ยนแปลงที่ยังไม่ได้บันทึกจะสูญหายหากยกเลิกการโหลดหน้าต่อไป
เนื่องจากมีเหตุผลอันสมควรในการใช้ beforeunload
เราจึงขอแนะนำให้คุณ
เฉพาะเพิ่ม Listener beforeunload
เมื่อผู้ใช้มีการเปลี่ยนแปลงที่ไม่ได้บันทึก จากนั้น
ให้ลบทันทีเมื่อบันทึก
พูดอีกอย่างคือ อย่าทำเช่นนี้ (เพราะระบบจะเพิ่มผู้ฟัง beforeunload
คน
โดยไม่มีเงื่อนไข)
addEventListener('beforeunload', (event) => {
// A function that returns `true` if the page has unsaved changes.
if (pageHasUnsavedChanges()) {
event.preventDefault();
// Legacy support for older browsers.
return (event.returnValue = true);
}
});
ให้ใช้วิธีนี้แทน (เนื่องจากจะเพิ่ม Listener beforeunload
เฉพาะเมื่อ
จำเป็น และนำออกเมื่อไม่จำเป็น):
const beforeUnloadListener = (event) => {
event.preventDefault();
// Legacy support for older browsers.
return (event.returnValue = true);
};
// A function that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges(() => {
addEventListener('beforeunload', beforeUnloadListener);
});
// A function that invokes a callback when the page's unsaved changes are resolved.
onAllChangesSaved(() => {
removeEventListener('beforeunload', beforeUnloadListener);
});
คำถามที่พบบ่อย
ทำไมจึงไม่มี "กำลังโหลด" คืออะไร
Page Lifecycle API จะกำหนดสถานะที่แยกจากกันและแยกจากกันโดยสิ้นเชิง เนื่องจากหน้าเว็บโหลดได้ทั้งในสถานะใช้งานอยู่ แบบแพสซีฟ หรือซ่อน และ เนื่องจากสามารถเปลี่ยนสถานะหรือสิ้นสุดการทำงานได้ก่อนที่แอปจะโหลดเสร็จ สถานะการโหลดที่แยกกันไม่สมเหตุสมผลในกระบวนทัศน์นี้
หน้าเว็บของฉันทำงานสำคัญเมื่อซ่อนอยู่ ฉันจะป้องกันไม่ให้หน้าเว็บถูกตรึงหรือยกเลิกได้อย่างไร
มีสาเหตุหลายประการที่ทำให้หน้าเว็บไม่ควรค้างขณะใช้งาน ในสถานะที่ซ่อนอยู่ ตัวอย่างที่เห็นได้ชัดที่สุดคือแอปที่เปิดเพลง
นอกจากนี้ยังมีบางกรณีที่ Chrome เสี่ยงที่จะยกเลิกหน้า
เช่น แบบฟอร์มมีแบบฟอร์มซึ่งมีข้อมูลที่ผู้ใช้ยกเลิกการส่ง หรือมี
เครื่องจัดการ beforeunload
ที่เตือนเมื่อหน้าเว็บกำลังยกเลิกการโหลด
ตอนนี้ Chrome จะยังไม่ระมัดระวังเมื่อทิ้งหน้าและ ดังนั้นให้สร้างเมื่อมั่นใจว่าจะไม่มีผลต่อผู้ใช้ ตัวอย่างเช่น หน้าที่ สามารถกระทำการใดๆ ต่อไปนี้ขณะที่อยู่ในสถานะที่ซ่อนอยู่ จะถูกทิ้งไป ยกเว้นภายใต้ข้อจำกัดทรัพยากรสุดโต่ง
- กำลังเล่นเสียง
- การใช้ WebRTC
- การอัปเดตชื่อตารางหรือไอคอน Fav
- การแสดงการแจ้งเตือน
- กำลังส่งข้อความ Push
สำหรับฟีเจอร์รายการปัจจุบันที่ใช้พิจารณาว่าแท็บจะปลอดภัยหรือไม่ ตรึงหรือทิ้ง ดูหัวข้อการวิเคราะห์การตรึงค่าและ กำลังทิ้ง ใน Chrome
แคชย้อนหลังเป็นคำที่ใช้อธิบาย การเพิ่มประสิทธิภาพการนำทาง บางเบราว์เซอร์มีการใช้งานที่จะพิจารณาการใช้ ปุ่มไปข้างหน้าให้เร็วขึ้น
เมื่อผู้ใช้ออกจากหน้าเว็บ เบราว์เซอร์จะหยุดเวอร์ชันของ
หน้านี้เพื่อให้กลับมาทำงานอีกครั้งได้อย่างรวดเร็ว ในกรณีที่ผู้ใช้ย้อนกลับโดยใช้
ปุ่มย้อนกลับหรือปุ่มไปข้างหน้า โปรดทราบว่าการเพิ่ม unload
ตัวแฮนเดิลเหตุการณ์ป้องกันไม่ให้ทำการเพิ่มประสิทธิภาพนี้ได้
สำหรับ Intent และวัตถุประสงค์ทั้งหมด การตรึงนี้จะทำงานเหมือนกับ เบราว์เซอร์ที่ค้างจะทำหน้าที่ประหยัด CPU/แบตเตอรี่ ด้วยเหตุผลดังกล่าว ถือว่าเป็นส่วนหนึ่งของสถานะของวงจรค้าง
หากเรียกใช้ API แบบไม่พร้อมกันในสถานะที่ค้างหรือสิ้นสุดไม่ได้ ฉันจะบันทึกข้อมูลลงใน IndexedDB ได้อย่างไร
ในสถานะถูกระงับและสิ้นสุดแล้ว งานที่ตรึงได้ ในคิวงานของหน้าเว็บ ถูกระงับ ซึ่งหมายถึง API แบบไม่พร้อมกันและ API ที่อิงตาม Callback เช่น IndexedDB อาจไม่น่าเชื่อถือ
ในอนาคต เราจะเพิ่มเมธอด commit()
ลงในออบเจ็กต์ IDBTransaction
ซึ่งจะ
ให้นักพัฒนาซอฟต์แวร์สามารถดำเนินการในธุรกรรมแบบเขียนเท่านั้นได้อย่างมีประสิทธิภาพ
ที่ไม่จำเป็นต้องมี Callback กล่าวคือ หากนักพัฒนาซอฟต์แวร์แค่เขียน
ไปยัง IndexedDB และไม่ดำเนินการธุรกรรมที่ซับซ้อนซึ่งประกอบด้วยการอ่าน
และการเขียน เมธอด commit()
จะเสร็จสิ้นได้ก่อนคิวงาน
ถูกระงับ (สมมติว่าฐานข้อมูล IndexedDB เปิดอยู่แล้ว)
อย่างไรก็ตาม สำหรับโค้ดที่ต้องใช้ในปัจจุบัน นักพัฒนาซอฟต์แวร์มี 2 ตัวเลือก ได้แก่
- ใช้พื้นที่เก็บข้อมูลเซสชัน: พื้นที่เก็บข้อมูลเซสชัน เป็นแบบซิงโครนัสและคงอยู่ในการยกเลิกหน้าเว็บ
- ใช้ IndexedDB จาก Service Worker: โปรแกรมทำงานของบริการจะจัดเก็บข้อมูลได้
IndexedDB หลังจากที่หน้าเว็บถูกสิ้นสุดหรือยกเลิก ใน
freeze
หรือ Listener เหตุการณ์pagehide
ที่คุณสามารถส่งข้อมูลไปยัง Service Worker ผ่านpostMessage()
และ Service Worker ช่วยจัดการบันทึกข้อมูลได้
การทดสอบแอปในสถานะหยุดค้างและถูกยกเลิก
หากต้องการทดสอบลักษณะการทำงานของแอปในสถานะหยุดค้างและถูกยกเลิก ให้ไปที่
chrome://discards
เพื่อตรึงหรือทิ้ง
แท็บที่เปิดอยู่
![Chrome ยกเลิก UI](https://developer.chrome.com/static/docs/web-platform/page-lifecycle-api/image/chrome-discards-ui-4c0620d6f8619.png?hl=th)
การดำเนินการนี้จะช่วยให้คุณมั่นใจได้ว่าหน้าเว็บจะจัดการ freeze
และ resume
อย่างถูกต้อง
เหตุการณ์ต่างๆ รวมทั้งธง document.wasDiscarded
เมื่อโหลดหน้าเว็บซ้ำหลังจาก
ทิ้ง
สรุป
นักพัฒนาแอปที่ต้องการเคารพทรัพยากรระบบของอุปกรณ์ของผู้ใช้ ควรสร้างแอปโดยคำนึงถึงสถานะของวงจรการใช้งานหน้าเว็บ จำเป็น หน้าเว็บไม่ใช้ทรัพยากรระบบมากเกินไปในกรณีที่ ผู้ใช้ไม่คาดคิด
ยิ่งนักพัฒนาซอฟต์แวร์เริ่มใช้ Page Lifecycle API ใหม่มากเท่าใด ก็จะยิ่งปลอดภัยมากขึ้นเท่านั้น จะทำให้เบราว์เซอร์ตรึงและทิ้งหน้าที่ไม่ได้ใช้งาน ช่วงเวลานี้ หมายความว่าเบราว์เซอร์จะใช้หน่วยความจำ, CPU, แบตเตอรี่ และทรัพยากรเครือข่ายน้อยลง ซึ่งจะเป็นประโยชน์สำหรับผู้ใช้