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

tl;dr

ตั้งแต่ Chrome 68 เป็นต้นไป ระบบจะไม่ดำเนินการคำขอ HTTP ที่ตรวจหาการอัปเดตของสคริปต์ Service Worker ด้วยแคช HTTP โดยค่าเริ่มต้นอีกต่อไป วิธีนี้เป็นการแก้ปัญหาปัญหาทั่วไปของนักพัฒนาซอฟต์แวร์ ซึ่งการตั้งค่าส่วนหัว Cache-Control โดยไม่ได้ตั้งใจในสคริปต์โปรแกรมทำงานของบริการอาจทำให้การอัปเดตล่าช้า

หากคุณเลือกไม่ใช้การแคช HTTP สำหรับสคริปต์ /service-worker.js โดยแสดงด้วย Cache-Control: max-age=0 แล้ว คุณจะไม่เห็นการเปลี่ยนแปลงเนื่องจากลักษณะการทำงานเริ่มต้นแบบใหม่

นอกจากนี้ ตั้งแต่ Chrome 78 เป็นต้นไป ระบบจะนำการเปรียบเทียบแบบไบต์ต่อไบต์ไปใช้กับสคริปต์ที่โหลดใน Service Worker ผ่าน importScripts() การเปลี่ยนแปลงใดก็ตามที่เกิดขึ้นกับสคริปต์ที่นำเข้าจะทริกเกอร์ขั้นตอนการอัปเดตโปรแกรมทำงานของบริการ เช่นเดียวกับที่การเปลี่ยนแปลงใน 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 ดังนั้นเว็บแอปพลิเคชันที่มีอยู่จึงอาจได้รับคำขอเพิ่มขึ้นสำหรับสคริปต์โปรแกรมทำงานของบริการ คำขอสำหรับ importScripts จะยังคงดำเนินการผ่านแคช HTTP แต่ตัวเลือกนี้เป็นค่าเริ่มต้น โดยตัวเลือกการลงทะเบียนใหม่คือ updateViaCache ที่ให้คุณควบคุมลักษณะการทำงานนี้ได้

updateViaCache

ตอนนี้นักพัฒนาแอปสามารถส่งตัวเลือกใหม่เมื่อเรียกใช้ navigator.serviceWorker.register(): พารามิเตอร์ updateViaCache โดยใช้ค่าใดค่าหนึ่งจาก 3 ค่า ซึ่งได้แก่ 'imports', 'all' หรือ 'none'

ค่าเหล่านี้จะเป็นตัวกำหนดว่าแคช HTTP มาตรฐานของเบราว์เซอร์จะเข้ามาทำงานหรือไม่และอย่างไรเมื่อส่งคำขอ HTTP เพื่อตรวจสอบทรัพยากรของ Service Worker ที่อัปเดต

  • เมื่อตั้งค่าเป็น 'imports' ระบบจะไม่พิจารณาแคช HTTP เมื่อตรวจหาการอัปเดตสคริปต์ /service-worker.js แต่จะปรึกษาเมื่อดึงข้อมูลสคริปต์ที่นำเข้า (เช่น path/to/import.js ในตัวอย่าง) ซึ่งเป็นค่าเริ่มต้น และตรงกับลักษณะการทำงานใน Chrome 68 เป็นต้นไป

  • เมื่อตั้งค่าเป็น 'all' ระบบจะพิจารณาแคช HTTP เมื่อส่งคำขอสำหรับทั้งสคริปต์ /service-worker.js ระดับบนสุด และสคริปต์ที่นำเข้าภายในโปรแกรมทำงานของบริการ เช่น 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 ของสคริปต์ ซึ่งโดยปกติจะเป็นการเพิ่มค่าเซมเวอร์ (เช่น importScripts('https://example.com/v1.1.0/index.js')) หรือใส่แฮชของเนื้อหา (เช่น importScripts('https://example.com/index.abcd1234.js')) ผลข้างเคียงของการเปลี่ยน URL ที่นำเข้าคือการเปลี่ยน URL เนื้อหาของโปรแกรมทำงานของบริการระดับบนสุด

ตั้งแต่ Chrome 78 เป็นต้นไป ทุกครั้งที่มีการตรวจหาการอัปเดตสำหรับไฟล์โปรแกรมทำงานระดับบนสุด การตรวจสอบจะเกิดขึ้นพร้อมกันเพื่อพิจารณาว่าเนื้อหาของสคริปต์ที่นำเข้ามีการเปลี่ยนแปลงหรือไม่ การตรวจสอบสคริปต์ที่นำเข้าเหล่านี้อาจได้รับการดำเนินการโดยแคช HTTP หากตั้งค่า updateViaCache เป็น 'all' หรือ 'imports' (ซึ่งเป็นค่าเริ่มต้น) หรือการตรวจสอบอาจเชื่อมต่อกับเครือข่ายโดยตรงหากตั้งค่า updateViaCache เป็น 'none' ทั้งนี้ขึ้นอยู่กับส่วนหัว Cache-Control ที่ใช้

หากการอัปเดตการตรวจหาสคริปต์ที่นำเข้าทำให้เกิดความแตกต่างแบบไบต์ต่อไบต์เมื่อเทียบกับข้อมูลที่ 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

เนื่องจากอาจมีผู้ใช้จำนวนมากในเบราว์เซอร์เวอร์ชันเก่า คุณจึงควรตั้งค่าส่วนหัว HTTP ของ Cache-Control: max-age=0 ในสคริปต์ Service Worker ต่อไป แม้ว่าเบราว์เซอร์ใหม่ๆ อาจไม่สนใจก็ตาม

นักพัฒนาซอฟต์แวร์สามารถใช้โอกาสนี้ในการตัดสินใจอย่างชัดเจนว่าต้องการเลือกไม่ใช้การแคช HTTP ที่นำเข้าอย่างชัดแจ้งในตอนนี้เลยหรือไม่ และเพิ่ม updateViaCache: 'none' ลงในการลงทะเบียนของ Service Worker ตามความเหมาะสม

การแสดงสคริปต์ที่นำเข้า

ตั้งแต่ Chrome 78 เป็นต้นไป นักพัฒนาแอปอาจเห็นคำขอ HTTP ขาเข้ามากขึ้นสำหรับทรัพยากรที่โหลดผ่าน importScripts() เนื่องจากตอนนี้จะได้รับการตรวจหาการอัปเดต

หากต้องการหลีกเลี่ยงการเข้าชม HTTP เพิ่มเติมนี้ ให้ตั้งค่าส่วนหัว Cache-Control ที่ใช้ได้นานเมื่อแสดงสคริปต์ที่มีเซมเวอร์หรือแฮชใน URL และใช้ลักษณะการทำงาน updateViaCache เริ่มต้นของ 'imports'

หรือถ้าคุณต้องการให้ตรวจหาอัปเดตของสคริปต์ที่นำเข้าเป็นประจำ ให้ตรวจสอบว่าคุณแสดงสคริปต์ดังกล่าวด้วย Cache-Control: max-age=0 หรือใช้ updateViaCache: 'none'

อ่านเพิ่มเติม

"The Service Worker Lifecycle" และ "แนวทางปฏิบัติแนะนำในการแคชและข้อผิดพลาดอายุสูงสุด" ซึ่งทั้ง Jake Archibald แนะนำให้อ่านสำหรับนักพัฒนาซอฟต์แวร์ทุกรายที่ใช้สิ่งต่างๆ ในเว็บได้