โมดูล Workbox จำนวน 1 รายการที่ยังไม่ครอบคลุมมากนักในเอกสารนี้คือ workbox-window
ซึ่งเป็นชุดโมดูลที่ตั้งใจจะใช้งานใน window
วัตถุประสงค์ของโมดูลนี้ได้แก่
- เพื่อให้การลงทะเบียนและการอัปเดตโปรแกรมทำงานของบริการง่ายขึ้นด้วยการช่วยนักพัฒนาซอฟต์แวร์ระบุช่วงเวลาสำคัญของวงจรการทำงานของโปรแกรมทำงาน ซึ่งทำให้การตอบสนองในช่วงเวลาดังกล่าวง่ายขึ้น
- เพื่อป้องกันไม่ให้นักพัฒนาซอฟต์แวร์ทำข้อผิดพลาดทั่วไป เช่น การลงทะเบียน Service Worker ในขอบเขตที่ไม่ถูกต้อง
- เพื่อให้การรับส่งข้อความระหว่าง
window
กับขอบเขต Service Worker ง่ายขึ้น
การนำเข้าและการใช้ workbox-window
การส่งออกที่คุณใช้บ่อยที่สุดจาก workbox-window
คือคลาส Workbox
ซึ่งคุณสามารถนำเข้าในโหนดหรือจาก CDN ในหน้าเว็บได้
การสร้างแพ็กเกจในเครื่อง
หาก Toolchain มี Bundler เช่น webpack หรือ Rollup คุณจะรวม workbox-window
ในเครื่องได้
ขั้นแรก ให้ติดตั้ง workbox-window
เป็นทรัพยากร Dependency ของแอปพลิเคชันจริงดังนี้
npm install workbox-window --save
จากนั้นใน JavaScript ของแอปพลิเคชัน คุณจะimport
คลาส Workbox
ได้จาก workbox-window
ดังนี้
<script type="module">
import {Workbox} from 'workbox-window';
if ('serviceWorker' in navigator) {
const wb = new Workbox('/sw.js');
wb.register();
}
</script>
แม้ว่า workbox-window
จะมีขนาดค่อนข้างเล็ก แต่คุณก็สามารถแยกค่าออกจากตรรกะแอปพลิเคชันหลักของเว็บไซต์โดยใช้ฟีเจอร์import
แบบไดนามิก ซึ่งจะลดขนาดกลุ่มหลักของหน้าได้ ดังนี้
<script type="module">
if ('serviceWorker' in navigator) {
const {Workbox} = await import('workbox-window');
const wb = new Workbox('/sw.js');
wb.register();
}
</script>
การใช้ CDN
แม้จะไม่ใช่วิธีการที่แนะนำ แต่วิธีใช้ workbox-window
ที่ง่ายกว่าคือการนำเข้าจาก CDN วิธีการมีดังนี้
<script type="module">
import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.2.0/workbox-window.prod.mjs';
if ('serviceWorker' in navigator) {
const wb = new Workbox('/sw.js');
wb.register();
}
</script>
โปรดทราบว่าองค์ประกอบ <script>
ในตัวอย่างด้านบนใช้แอตทริบิวต์ type="module"
คุณจำเป็นต้องดำเนินการนี้หากต้องการใช้คำสั่ง import
แบบคงที่ในเบราว์เซอร์โดยไม่มีขั้นตอนการสร้าง เบราว์เซอร์หลักๆ ทั้งหมดที่รองรับโปรแกรมทำงานของบริการรองรับโมดูล JavaScript ด้วย ดังนั้น แสดงโค้ดนี้ในเบราว์เซอร์ใดก็ได้ เนื่องจากเบราว์เซอร์รุ่นเก่าจะไม่สนใจองค์ประกอบ <script>
ที่มีค่าแอตทริบิวต์ type
เป็น "module"
การลงทะเบียน Service Worker
การลงทะเบียน Service Worker ด้วย workbox-window
จะดำเนินการโดยใช้เมธอด register
ของคลาส Workbox
ดังนี้
import {Workbox} from 'workbox-window';
const wb = new Workbox('/sw.js');
wb.register();
ดูเหมือนว่านี่จะเหมือนกับการลงทะเบียนโปรแกรมทำงานของบริการด้วยตัวคุณเองโดยใช้ navigator.serviceWorker.register
แต่ Workbox.register
จะรอจนกว่าเหตุการณ์ window
load
จึงจะลงทะเบียน Service Worker ได้ วิธีนี้เหมาะสำหรับกรณีที่ต้องมีการแคชล่วงหน้า ดังนั้นการช่วงชิงแบนด์วิดท์อาจทำให้การเริ่มต้นหน้าเว็บล่าช้าได้
การสื่อสารระหว่าง window
กับขอบเขตของ Service Worker
โปรแกรมทำงานของบริการมีขอบเขตของตนเองแยกต่างหากจาก window
และมีสิทธิ์เข้าถึง API บางส่วนที่มีใน window
เท่านั้น อย่างไรก็ตาม คุณสามารถสื่อสารระหว่าง window
กับ Service Worker ได้ workbox-window
ช่วยให้สื่อสารระหว่าง 2 ขอบเขตได้ง่ายขึ้นด้วยเมธอด messageSW
ของโมดูล workbox-window
โดย Workbox จะใช้รูปแบบที่เฉพาะเจาะจงสำหรับข้อความ โดยเป็นออบเจ็กต์ที่มีพร็อพเพอร์ตี้ดังต่อไปนี้
type
คือสตริงที่ไม่ซ้ำกันซึ่งต้องระบุเพื่อระบุข้อความ รูปแบบควรเป็นตัวพิมพ์ใหญ่ และมีขีดล่างที่แยกคำ (เช่นCACHE_URLS
)meta
เป็นสตริงที่ไม่บังคับซึ่งแสดงชื่อของแพ็กเกจ Workbox ที่ส่งข้อความ และโดยปกติจะละเว้นไว้payload
เป็นพารามิเตอร์ที่ไม่บังคับซึ่งแสดงข้อมูลที่คุณต้องการส่ง ซึ่งอาจเป็นข้อมูลประเภทใดก็ได้
ด้านล่างนี้เป็นตัวอย่างวิธีการทำงานของ messageSW
โดยเริ่มต้นด้วยโค้ดใน Service Worker ของคุณ ดังนี้
// sw.js
const SW_VERSION = '1.0.0';
self.addEventListener('message', (event) => {
if (event.data.type === 'GET_VERSION') {
event.ports[0].postMessage(SW_VERSION);
}
});
ตามด้วยโค้ดต่อไปนี้ในหน้าเว็บของคุณ
const wb = new Workbox('/sw.js');
wb.register();
const swVersion = await wb.messageSW({type: 'GET_VERSION'});
console.log('Service Worker version:', swVersion);
มีหลายกรณีที่การสื่อสารระหว่าง Service Worker กับ window
ก็มีประโยชน์ เช่น การแจ้งผู้ใช้เมื่อมีอัปเดตโปรแกรมทำงานของบริการ สูตรดังกล่าวอาศัยวิธีการผู้ช่วยพิเศษสําหรับ self.skipWaiting
ที่ชื่อ messageSkipWaiting
ซึ่งส่งข้อความที่มีค่า type
เป็น SKIP_WAITING