การใช้หน้าต่างกล่องงาน

โมดูลช่องงาน 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