โปรแกรมทำงานของบริการที่ใหม่กว่าโดยค่าเริ่มต้น

สรุปสั้นๆ

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