สรุปสั้นๆ
ตั้งแต่ 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 ชั่วโมง) ระบบจะถือว่า max-age
เป็น 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 เราขอแนะนำให้นักพัฒนาซอฟต์แวร์ทุกคนที่ติดตั้งใช้งานสิ่งใดก็ตามบนเว็บอ่าน