สรุปสั้นๆ
ตั้งแต่ Chrome 68 เป็นต้นไป แคช HTTP จะไม่ตอบสนองต่อคำขอ HTTP ที่ตรวจสอบการอัปเดตสคริปต์ Service Worker โดยค่าเริ่มต้นอีกต่อไป วิธีนี้ช่วยแก้ปัญหาที่นักพัฒนาซอฟต์แวร์พบได้ทั่วไป ซึ่งการตั้งค่าส่วนหัว Cache-Control
โดยไม่ตั้งใจในสคริปต์ Service Worker อาจทําให้อัปเดตล่าช้า
หากคุณเลือกไม่ใช้การแคช HTTP สําหรับสคริปต์ /service-worker.js
อยู่แล้วโดยแสดงสคริปต์ด้วย Cache-Control: max-age=0
คุณจะไม่พบการเปลี่ยนแปลงใดๆ เนื่องจากลักษณะการทํางานเริ่มต้นใหม่
นอกจากนี้ ตั้งแต่ Chrome 78 เป็นต้นไป ระบบจะใช้การเปรียบเทียบแบบไบต์ต่อไบต์กับสคริปต์ที่โหลดใน Service Worker ผ่าน importScripts()
การเปลี่ยนแปลงใดๆ ที่ทำกับสคริปต์ที่นําเข้าจะทริกเกอร์ขั้นตอนการอัปเดต Service Worker เช่นเดียวกับการเปลี่ยนแปลง Service Worker ระดับบนสุด
ข้อมูลเบื้องต้น
ทุกครั้งที่คุณไปยังหน้าใหม่ที่อยู่ภายใต้ขอบเขตของ Service Worker ให้เรียก registration.update()
อย่างชัดเจนจาก JavaScript หรือเมื่อ "ปลุก" Service Worker ผ่านเหตุการณ์ push
หรือ sync
เบราว์เซอร์จะส่งคําขอทรัพยากร JavaScript ที่ส่งไปยังการเรียก navigator.serviceWorker.register()
เดิมไปพร้อมๆ กัน เพื่อค้นหาการอัปเดตสคริปต์ Service Worker
บทความนี้สมมติว่า URL ของหน้าเว็บคือ /service-worker.js
และมีคำเรียก importScripts()
เพียงครั้งเดียว ซึ่งจะโหลดโค้ดเพิ่มเติมที่ทำงานภายใน Service Worker ดังนี้
// Inside our /service-worker.js file:
importScripts('path/to/import.js');
// Other top-level code goes here.
สิ่งที่เปลี่ยนแปลงไป
ก่อน Chrome 68 คำขออัปเดต /service-worker.js
จะส่งผ่านแคช HTTP (เช่นเดียวกับการดึงข้อมูลส่วนใหญ่) ซึ่งหมายความว่าหากส่งสคริปต์ด้วย Cache-Control:
max-age=600
ไว้ตั้งแต่แรก การอัปเดตภายใน 600 วินาที (10 นาที) ถัดไปจะไม่ส่งไปยังเครือข่าย ดังนั้นผู้ใช้อาจไม่ได้รับ Service Worker เวอร์ชันล่าสุด อย่างไรก็ตาม หาก max-age
มีค่ามากกว่า 86400 (24 ชั่วโมง) ระบบจะถือว่ามีค่าเท่ากับ 86400 เพื่อไม่ให้ผู้ใช้ติดอยู่กับเวอร์ชันใดเวอร์ชันหนึ่งตลอดไป
ตั้งแต่เวอร์ชัน 68 เป็นต้นไป ระบบจะไม่สนใจแคช HTTP เมื่อขอการอัปเดตสคริปต์ Service Worker ดังนั้นแอปพลิเคชันเว็บที่มีอยู่อาจเห็นความถี่ของคำขอสคริปต์ Service Worker เพิ่มขึ้น คำขอ importScripts
จะยังคงส่งผ่านแคช HTTP แต่นี่เป็นค่าเริ่มต้นเท่านั้น ตัวเลือกการลงทะเบียนใหม่ updateViaCache
มีให้ใช้งานเพื่อควบคุมลักษณะการทำงานนี้
updateViaCache
ตอนนี้นักพัฒนาแอปสามารถส่งตัวเลือกใหม่เมื่อเรียกใช้ navigator.serviceWorker.register()
: พารามิเตอร์ updateViaCache
โดยค่านี้ต้องเป็นค่าใดค่าหนึ่งต่อไปนี้ 'imports'
, 'all'
หรือ 'none'
ค่าเหล่านี้จะกำหนดว่า แคช HTTP มาตรฐานของเบราว์เซอร์จะทำงานหรือไม่และอย่างไรเมื่อส่งคำขอ HTTP เพื่อตรวจสอบทรัพยากร Service Worker ที่อัปเดต
เมื่อตั้งค่าเป็น
'imports'
ระบบจะไม่ใช้แคช HTTP เมื่อตรวจสอบการอัปเดตสคริปต์/service-worker.js
แต่จะใช้เมื่อดึงข้อมูลสคริปต์ที่นำเข้า (path/to/import.js
ในตัวอย่างของเรา) ซึ่งเป็นค่าเริ่มต้นและตรงกับลักษณะการทำงานที่เริ่มตั้งแต่ Chrome 68เมื่อตั้งค่าเป็น
'all'
ระบบจะปรึกษาแคช HTTP เมื่อส่งคําขอสคริปต์/service-worker.js
ระดับบนสุด รวมถึงสคริปต์ที่นําเข้าภายใน Service Worker เช่นpath/to/import.js
ตัวเลือกนี้สอดคล้องกับลักษณะการทำงานก่อนหน้าใน Chrome ก่อน Chrome เวอร์ชัน 68เมื่อตั้งค่าเป็น
'none'
ระบบจะไม่ใช้แคช HTTP เมื่อส่งคําขอ/service-worker.js
ระดับบนสุดหรือสคริปต์ที่นําเข้า เช่นpath/to/import.js
สมมติ
ตัวอย่างเช่น โค้ดต่อไปนี้จะลงทะเบียน Service Worker และตรวจสอบว่าไม่มีการปรึกษาแคช HTTP เมื่อตรวจสอบการอัปเดตสคริปต์ /service-worker.js
หรือสคริปต์ที่อ้างอิงผ่าน importScripts()
ภายใน /service-worker.js
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js', {
updateViaCache: 'none',
// Optionally, set 'scope' here, if needed.
});
}
ตรวจหาการอัปเดตสคริปต์ที่นำเข้า
ก่อนที่จะมี Chrome 78 สคริปต์ Service Worker ที่โหลดผ่าน importScripts()
จะดึงข้อมูลเพียงครั้งเดียว (ตรวจสอบกับแคช HTTP ก่อน หรือผ่านเครือข่าย ทั้งนี้ขึ้นอยู่กับการกำหนดค่า updateViaCache
) หลังจากการดึงข้อมูลครั้งแรก เบราว์เซอร์จะจัดเก็บข้อมูลดังกล่าวไว้ในระบบและจะไม่ดึงข้อมูลอีกครั้ง
วิธีเดียวที่จะบังคับให้ Service Worker ที่ติดตั้งไว้แล้วรับการเปลี่ยนแปลงสคริปต์ที่นําเข้าคือการเปลี่ยน URL ของสคริปต์ ซึ่งโดยปกติแล้วจะเป็นการเพิ่มค่า semver (เช่น importScripts('https://example.com/v1.1.0/index.js')
) หรือใส่แฮชของเนื้อหา (เช่น importScripts('https://example.com/index.abcd1234.js')
) ผลข้างเคียงของการเปลี่ยน URL ที่นําเข้าคือเนื้อหาของสคริปต์ Service Worker ระดับบนสุดจะเปลี่ยนแปลง ซึ่งจะทริกเกอร์ขั้นตอนการอัปเดต Service Worker
ตั้งแต่ Chrome 78 เป็นต้นไป ทุกครั้งที่ระบบจะตรวจสอบการอัปเดตไฟล์ Service Worker ระดับบนสุด ระบบจะตรวจสอบเนื้อหาของสคริปต์ที่นำเข้าเพื่อดูว่ามีการเปลี่ยนแปลงหรือไม่ การตรวจสอบสคริปต์ที่นําเข้าเหล่านี้อาจดำเนินการโดยแคช HTTP หากตั้งค่า updateViaCache
เป็น 'all'
หรือ 'imports'
(ซึ่งเป็นค่าเริ่มต้น) หรือการตรวจสอบอาจดำเนินการกับเครือข่ายโดยตรงหากตั้งค่า updateViaCache
เป็น 'none'
ทั้งนี้ขึ้นอยู่กับส่วนหัว Cache-Control
ที่ใช้
หากการตรวจสอบการอัปเดตสคริปต์ที่นําเข้าส่งผลให้มีความแตกต่างแบบไบต์ต่อไบต์เมื่อเทียบกับสิ่งที่ Service Worker จัดเก็บไว้ก่อนหน้านี้ การดำเนินการดังกล่าวจะทริกเกอร์ขั้นตอนการอัปเดต Service Worker แบบสมบูรณ์ แม้ว่าไฟล์ Service Worker ระดับบนสุดจะยังคงเหมือนเดิมก็ตาม
ลักษณะการทํางานของ Chrome 78 ตรงกับสิ่งที่ Firefox นํามาใช้เมื่อหลายปีก่อนใน Firefox 56 Safari ใช้ลักษณะการทำงานนี้อยู่แล้ว
นักพัฒนาแอปต้องทําอะไรบ้าง
หากคุณเลือกไม่ใช้การแคช HTTP สําหรับสคริปต์ /service-worker.js
ได้อย่างมีประสิทธิภาพแล้วโดยแสดงสคริปต์นั้นด้วย Cache-Control: max-age=0
(หรือค่าที่คล้ายกัน) คุณจะไม่พบการเปลี่ยนแปลงใดๆ เนื่องจากลักษณะการทํางานเริ่มต้นใหม่
หากคุณแสดงสคริปต์ /service-worker.js
โดยเปิดใช้การแคช HTTP ไม่ว่าจะตั้งใจหรือไม่ตั้งใจ หรือเพราะนี่เป็นค่าเริ่มต้นสำหรับสภาพแวดล้อมโฮสติ้ง คุณอาจเริ่มเห็นคําขอ HTTP เพิ่มเติมสําหรับ /service-worker.js
ที่ส่งไปยังเซิร์ฟเวอร์ของคุณเพิ่มขึ้น ซึ่งคําขอเหล่านี้เคยได้รับการตอบสนองจากแคช HTTP หากต้องการอนุญาตให้ค่าส่วนหัว Cache-Control
ส่งผลต่อความใหม่ของ /service-worker.js
ต่อไป คุณจะต้องเริ่มตั้งค่า updateViaCache: 'all'
อย่างชัดเจนเมื่อลงทะเบียน Service Worker
เนื่องจากอาจมีผู้ใช้จำนวนมากที่ใช้เบราว์เซอร์เวอร์ชันเก่าอยู่ คุณจึงควรตั้งค่าส่วนหัว Cache-Control: max-age=0
HTTP ในสคริปต์ Service Worker ต่อไป แม้ว่าเบราว์เซอร์เวอร์ชันใหม่อาจไม่สนใจก็ตาม
นักพัฒนาแอปสามารถใช้โอกาสนี้เพื่อตัดสินใจว่าต้องการเลือกไม่ให้สคริปต์ที่นําเข้าใช้การแคช HTTP อย่างชัดเจนในตอนนี้หรือไม่ และเพิ่ม updateViaCache: 'none'
ในการลงทะเบียน Service Worker หากเหมาะสม
การแสดงสคริปต์ที่นําเข้า
ตั้งแต่ Chrome 78 เป็นต้นไป นักพัฒนาซอฟต์แวร์อาจเห็นคำขอ HTTP ขาเข้าสำหรับทรัพยากรที่โหลดผ่าน importScripts()
มากขึ้น เนื่องจากระบบจะตรวจสอบทรัพยากรดังกล่าวเพื่อหาการอัปเดต
หากต้องการหลีกเลี่ยงการรับส่งข้อมูล HTTP เพิ่มเติมนี้ ให้ตั้งค่าส่วนหัว Cache-Control
ที่ใช้ได้นานเมื่อแสดงสคริปต์ที่มี semver หรือแฮชใน URL และใช้ลักษณะการทำงาน updateViaCache
เริ่มต้นของ 'imports'
หรือหากต้องการให้มีการตรวจสอบสคริปต์ที่นำเข้าเพื่อหาการอัปเดตบ่อยๆ โปรดตรวจสอบว่าคุณแสดงสคริปต์ด้วย Cache-Control: max-age=0
หรือใช้ updateViaCache: 'none'
อ่านเพิ่มเติม
"วงจรชีวิตของ Service Worker" และ "แนวทางปฏิบัติแนะนำในการแคชและข้อควรระวังเกี่ยวกับ max-age" ทั้งสองบทความนี้เขียนโดย Jake Archibald เราขอแนะนำให้นักพัฒนาซอฟต์แวร์ทุกคนที่ติดตั้งใช้งานสิ่งใดก็ตามบนเว็บอ่าน