โมดูลช่องงาน 1 โมดูลที่ยังไม่ค่อยครอบคลุมในเอกสารประกอบนี้คือ workbox-window
ซึ่งเป็นชุดโมดูลที่มีไว้เพื่อทำงานใน window
เป้าหมายของโมดูลนี้คือ
- เพื่อลดความซับซ้อนในการลงทะเบียนและการอัปเดต Service Worker โดยช่วยให้นักพัฒนาแอประบุช่วงเวลาสําคัญของวงจร Service Worker ได้ ซึ่งช่วยให้ตอบสนองได้ง่ายขึ้นในช่วงเวลาดังกล่าว
- เพื่อป้องกันไม่ให้นักพัฒนาแอปทำข้อผิดพลาดที่พบบ่อย เช่น การลงทะเบียน Service Worker ในขอบเขตที่ไม่ถูกต้อง
- เพื่อลดความซับซ้อนของการรับส่งข้อความระหว่าง
window
กับขอบเขต Service Worker
กำลังนำเข้าและการใช้ workbox-window
การส่งออกที่คุณจะใช้บ่อยที่สุดจาก workbox-window
คือคลาส Workbox
ซึ่งจะนำเข้าในโหนดหรือจาก CDN ในหน้าเว็บก็ได้
การสร้างแพ็กเกจในเครื่อง
หากเครื่องมือเชนมี Bundler เช่น Webpack หรือ Rollup คุณรวมกลุ่ม workbox-window
ไว้ในเครื่องได้
ก่อนอื่น ให้ติดตั้ง workbox-window
เป็นส่วนประกอบที่ต้องใช้ในเวอร์ชันที่ใช้งานจริงของแอปพลิเคชัน
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();
ซึ่งอาจเหมือนกับการลงทะเบียน Service Worker ด้วยตนเองโดยใช้ 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