หน้าต่างกล่องงาน

แพ็กเกจ workbox-window คือชุดโมดูลที่มีไว้ทำงานใน window บริบท ซึ่ง ก็คือภายในหน้าเว็บของคุณ ซึ่งช่วยส่งเสริมกล่องงานอื่นๆ ที่เรียกใช้ในโปรแกรมทำงานของบริการ

ฟีเจอร์/เป้าหมายหลักของ workbox-window มีดังนี้

การนำเข้าและการใช้หน้าต่างงาน

จุดแรกเข้าหลักสำหรับแพ็กเกจ workbox-window คือคลาส Workbox และ คุณสามารถนำเข้า URL ดังกล่าวในโค้ดจาก CDN ของเราหรือใช้รายการ เครื่องมือการรวมกลุ่ม JavaScript

การใช้ CDN ของเรา

วิธีที่ง่ายที่สุดในการนำเข้าคลาส Workbox ในเว็บไซต์ของคุณคือจาก CDN ของเรา

<script type="module">
  import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-window.prod.mjs';

  if ('serviceWorker' in navigator) {
    const wb = new Workbox('/sw.js');

    wb.register();
  }
</script>

โปรดทราบว่าตัวอย่างนี้ใช้ <script type="module"> และคำสั่ง import เพื่อ โหลดชั้นเรียน Workbox คุณอาจคิดว่าจำเป็นต้องเปลี่ยนข้อมูล เพื่อทำให้โค้ดทำงานในเบราว์เซอร์รุ่นเก่า ซึ่งไม่ใช่ความจำเป็นจริงๆ

เบราว์เซอร์หลักทั้งหมดที่โปรแกรมทำงานสนับสนุนบริการยังรองรับโมดูล JavaScript แบบเนทีฟด้วย ดังนั้นจึงทำได้เต็มที่ แสดงโค้ดนี้ในทุกเบราว์เซอร์ได้ (เบราว์เซอร์รุ่นเก่าจะไม่สนใจโค้ดนี้)

กำลังโหลด Workbox ด้วย Bundler JavaScript

คุณไม่จำเป็นต้องใช้เครื่องมือใดๆ เลยในการใช้ workbox-window แต่ถ้า โครงสร้างพื้นฐานของการพัฒนา มี Bundler อย่าง Webpack หรือ Rollup ที่ใช้งานได้ ด้วยทรัพยากร Dependency npm คุณจะนําไปใช้เพื่อ โหลด workbox-window

ขั้นตอนแรกคือ ติดตั้ง workbox-window เป็นทรัพยากร Dependency สำหรับแอปพลิเคชันของคุณ:

npm install workbox-window

จากนั้นในไฟล์ JavaScript ของแอปพลิเคชัน import ช่องงานโดย อ้างอิงชื่อแพ็กเกจ workbox-window

import {Workbox} from 'workbox-window';

if ('serviceWorker' in navigator) {
  const wb = new Workbox('/sw.js');

  wb.register();
}

หาก Bundler ของคุณรองรับการแยกโค้ดผ่านคำสั่งการนำเข้าแบบไดนามิก คุณยังโหลด workbox-window แบบมีเงื่อนไขได้ด้วย ซึ่งจะช่วยลด ของแพ็กเกจหลักของหน้าเว็บ

แม้ว่า workbox-window จะค่อนข้างเล็ก แต่ก็ไม่มีเหตุผล จำเป็นต้องโหลดด้วยตรรกะแอปพลิเคชันหลักของเว็บไซต์ ในฐานะโปรแกรมทำงานของบริการ โดยธรรมชาติแล้ว ถือว่าเป็นการปรับปรุงที่ก้าวหน้า

if ('serviceWorker' in navigator) {
  const {Workbox} = await import('workbox-window');

  const wb = new Workbox('/sw.js');
  wb.register();
}

แนวคิดการรวมกลุ่มขั้นสูง

ไฟล์บิลด์จะต่างจากแพ็กเกจ Workbox ที่เรียกใช้ในโปรแกรมทำงานของบริการ ที่อ้างอิงโดย workbox-window main และ module ช่องใน package.json แปลงเป็น ES5 ซึ่งทำให้เข้ากับ เครื่องมือบิลด์ บางรายการที่ไม่อนุญาตให้นักพัฒนาซอฟต์แวร์แปลงข้อมูล ทรัพยากร Dependency ของ node_module

หากระบบของบิลด์อนุญาตให้คุณแปลงทรัพยากร Dependency (หรือหากคุณ คุณควรนำเข้าโค้ด ไฟล์ต้นฉบับ แทนที่จะเป็นตัวแพ็กเกจ

ต่อไปนี้คือวิธีต่างๆ ในการนำเข้า Workbox พร้อมด้วยคำอธิบายของ สิ่งที่แต่ละชิ้นจะส่งคืน

// Imports a UMD version with ES5 syntax
// (pkg.main: "build/workbox-window.prod.umd.js")
const {Workbox} = require('workbox-window');

// Imports the module version with ES5 syntax
// (pkg.module: "build/workbox-window.prod.es5.mjs")
import {Workbox} from 'workbox-window';

// Imports the module source file with ES2015+ syntax
import {Workbox} from 'workbox-window/Workbox.mjs';

ตัวอย่าง

เมื่อนำเข้าชั้นเรียน Workbox แล้ว คุณจะใช้ชั้นเรียนเพื่อลงทะเบียนและ โต้ตอบกับ Service Worker ตัวอย่างวิธีที่คุณอาจนำไปใช้ได้มีดังนี้ Workbox ในแอปพลิเคชันของคุณ:

ลงทะเบียน Service Worker และแจ้งให้ผู้ใช้ทราบในครั้งแรกที่โปรแกรมทำงานของบริการ

โปรแกรมทำงานของบริการผู้ใช้เว็บแอปพลิเคชันจำนวนมากที่จะแคชเนื้อหาล่วงหน้าเพื่อให้แอปทำงานได้ ออฟไลน์เมื่อโหลดหน้าเว็บที่ตามมา การแจ้งข้อมูลในบางกรณีเป็นเรื่องสมเหตุสมผล ผู้ใช้ที่แอปนี้พร้อมใช้งานแบบออฟไลน์แล้ว

const wb = new Workbox('/sw.js');

wb.addEventListener('activated', event => {
  // `event.isUpdate` will be true if another version of the service
  // worker was controlling the page when this version was registered.
  if (!event.isUpdate) {
    console.log('Service worker activated for the first time!');

    // If your service worker is configured to precache assets, those
    // assets should all be available now.
  }
});

// Register the service worker after event listeners have been added.
wb.register();

แจ้งให้ผู้ใช้ทราบหากโปรแกรมทำงานของบริการได้ติดตั้งแล้ว แต่ต้องรอการเปิดใช้งาน

เมื่อหน้าเว็บที่ควบคุมโดย Service Worker ที่มีอยู่ลงทะเบียนบริการใหม่ โดยค่าเริ่มต้นโปรแกรมทำงานของบริการจะไม่เปิดใช้งานจนกว่าไคลเอ็นต์ทั้งหมด ซึ่งควบคุมโดย Service Worker เริ่มต้น ได้ยกเลิกการโหลดอย่างสมบูรณ์

ซึ่งเป็นสาเหตุที่พบบ่อยที่ทำให้นักพัฒนาซอฟต์แวร์สับสน โดยเฉพาะอย่างยิ่งในกรณีที่ การโหลดหน้าเว็บปัจจุบันซ้ำจะไม่ทำให้ Service Worker ใหม่เปิดใช้งาน

เพื่อช่วยลดความสับสนและอธิบายให้ชัดเจนเมื่อเกิดเหตุการณ์นี้ขึ้น ชั้นเรียน Workbox มีเหตุการณ์ waiting ที่คุณฟังได้:

const wb = new Workbox('/sw.js');

wb.addEventListener('waiting', event => {
  console.log(
    `A new service worker has installed, but it can't activate` +
      `until all tabs running the current version have fully unloaded.`
  );
});

// Register the service worker after event listeners have been added.
wb.register();

แจ้งเตือนผู้ใช้เกี่ยวกับการอัปเดตแคชจากแพ็กเกจ workbox-broadcast-update

แพ็กเกจ workbox-broadcast-update เป็นวิธีที่ยอดเยี่ยมในการแสดงเนื้อหาจากแคช (เพื่อการนำส่งที่รวดเร็ว) สามารถแจ้งให้ผู้ใช้ทราบถึงการอัปเดตเนื้อหานั้น (โดยใช้ กลยุทธ์ที่ไม่มีการอัปเดตขณะตรวจสอบความถูกต้องอีกครั้ง)

หากต้องการรับการอัปเดตเหล่านั้นจากหน้าต่าง คุณสามารถฟังเหตุการณ์ message ของ ประเภท CACHE_UPDATED:

const wb = new Workbox('/sw.js');

wb.addEventListener('message', event => {
  if (event.data.type === 'CACHE_UPDATED') {
    const {updatedURL} = event.data.payload;

    console.log(`A newer version of ${updatedURL} is available!`);
  }
});

// Register the service worker after event listeners have been added.
wb.register();

ส่งรายการ URL ที่จะแคชให้กับโปรแกรมทำงานของบริการ

สำหรับบางแอปพลิเคชัน คุณสามารถทราบเนื้อหาทั้งหมดที่จำเป็นต้องมี มีการแคชล่วงหน้า ณ เวลาสร้าง แต่แอปพลิเคชันบางรายการแสดงหน้าเว็บที่แตกต่างกันโดยสิ้นเชิง ขึ้นอยู่กับ URL ที่ผู้ใช้เข้าชมเป็นอันดับแรก

สำหรับแอปในหมวดหมู่หลัง คุณควรแคชเฉพาะเนื้อหา ที่ผู้ใช้ต้องการสำหรับหน้าหนึ่งๆ ที่เข้าชม เมื่อใช้ แพ็กเกจ workbox-routing คุณสามารถ ส่งรายการ URL เพื่อแคชให้กับเราเตอร์ของคุณ จากนั้นระบบจะแคช URL เหล่านั้นตาม ตามกฎที่กำหนดไว้ในเราเตอร์เอง

ตัวอย่างนี้จะส่งรายการ URL ที่โหลดโดยหน้าเว็บไปยังเราเตอร์เมื่อใดก็ตามที่ มีการเปิดใช้งาน Service Worker ใหม่ โปรดทราบว่าคุณสามารถส่ง URL ทั้งหมด เนื่องจากมีเพียง ระบบจะแคช URL ที่ตรงกับเส้นทางที่กำหนดไว้ใน Service Worker ดังนี้

const wb = new Workbox('/sw.js');

wb.addEventListener('activated', event => {
  // Get the current page URL + all resources the page loaded.
  const urlsToCache = [
    location.href,
    ...performance.getEntriesByType('resource').map(r => r.name),
  ];
  // Send that list of URLs to your router in the service worker.
  wb.messageSW({
    type: 'CACHE_URLS',
    payload: {urlsToCache},
  });
});

// Register the service worker after event listeners have been added.
wb.register();

ช่วงเวลาที่สำคัญในวงจรของโปรแกรมทำงานของบริการ

วงจรชีวิตของโปรแกรมทำงานของบริการ นั้นเป็นเรื่องซับซ้อนและอาจเป็นเรื่องที่ท้าทายในการทำความเข้าใจ สาเหตุส่วนหนึ่งคือ มีความซับซ้อนมากจนต้องจัดการกับ กรณีปัญหาทั้งหมดสำหรับการใช้งานที่เป็นไปได้ทั้งหมด Service Worker (เช่น การลงทะเบียน Service Worker มากกว่า 1 โปรแกรม, การลงทะเบียน Service Worker ที่อยู่คนละเฟรม ลงทะเบียน Service Worker ชื่ออื่น เป็นต้น)

แต่นักพัฒนาซอฟต์แวร์ส่วนใหญ่ที่ใช้โปรแกรมทำงานของบริการ (Service Worker) ไม่ควรจะต้องกังวลเรื่อง ทั้งหมดนี้เพราะการใช้งานนั้นค่อนข้างง่าย นักพัฒนาแอปส่วนใหญ่ ลงทะเบียน Service Worker เพียง 1 รายการต่อการโหลดหน้าเว็บ 1 ครั้ง โดยบุคคลเหล่านั้นจะไม่เปลี่ยนชื่อโปรแกรมทำงานของบริการ ไฟล์ที่พวกเขาทำให้ใช้งานได้ในเซิร์ฟเวอร์

คลาส Workbox ยอมรับมุมมองที่เรียบง่ายขึ้นสำหรับวงจรชีวิตของ Service Worker โดยการแบ่งการลงทะเบียนโปรแกรมทำงานของบริการทั้งหมดออกเป็น 2 หมวดหมู่ ได้แก่ เป็น Service Worker ที่ลงทะเบียนแล้ว และ Service Worker ภายนอก

  • Service Worker ที่จดทะเบียน: โปรแกรมทำงานของบริการที่เริ่มการติดตั้งเป็น ผลลัพธ์ของอินสแตนซ์ Workbox ที่เรียกใช้ register() หรือมีการใช้งานแล้ว Service Worker หากการเรียกใช้ register() ไม่ทริกเกอร์เหตุการณ์ updatefound ในการลงทะเบียน
  • โปรแกรมทำงานของบริการภายนอก: โปรแกรมทำงานของบริการที่เริ่มการติดตั้ง โดยไม่ขึ้นอยู่กับอินสแตนซ์ Workbox ที่เรียกใช้ register() โดยปกติ เกิดขึ้นเมื่อผู้ใช้เปิดเว็บไซต์เวอร์ชันใหม่ของคุณในอีกแท็บหนึ่ง เมื่อ เหตุการณ์มาจาก Service Worker ภายนอก ซึ่งเป็น isExternal พร็อพเพอร์ตี้จะถูกตั้งค่าเป็น true

ด้วยคำนึงถึง Service Worker ทั้ง 2 ประเภท ต่อไปนี้คือรายละเอียด ช่วงเวลาที่สำคัญในวงจรของโปรแกรมทำงานของบริการ รวมถึงคำแนะนำของนักพัฒนาซอฟต์แวร์ สำหรับวิธีจัดการ

ครั้งแรกที่ติดตั้งโปรแกรมทำงานของบริการ

อาจต้องทำตามขั้นตอนที่ติดตั้ง Service Worker ในครั้งแรก แตกต่างจากวิธีจัดการการอัปเดตทั้งหมดในอนาคต

คุณแยกความแตกต่างระหว่างเวอร์ชันต่างๆ ได้ใน workbox-window การติดตั้งและการอัปเดตในอนาคต โดยตรวจสอบพร็อพเพอร์ตี้ isUpdate ใน เหตุการณ์ต่อไปนี้ สำหรับการติดตั้งครั้งแรก isUpdate จะ false

const wb = new Workbox('/sw.js');

wb.addEventListener('installed', event => {
  if (!event.isUpdate) {
    // First-installed code goes here...
  }
});

wb.register();
ช่วงเวลาสำคัญ กิจกรรม การดำเนินการที่แนะนำ
มีการติดตั้งโปรแกรมทำงานของบริการใหม่ (เป็นครั้งแรก) installed

เมื่อติดตั้ง Service Worker เป็นครั้งแรก ถือเป็นเรื่องปกติที่จะทำการแคชล่วงหน้า เนื้อหาทั้งหมดที่จำเป็นต่อการทำงานแบบออฟไลน์ของเว็บไซต์ คุณอาจลองใช้ เพื่อแจ้งให้ผู้ใช้ทราบว่าตอนนี้เว็บไซต์ทำงานแบบออฟไลน์ได้แล้ว

และตั้งแต่ครั้งแรกที่โปรแกรมทำงานของบริการติดตั้งโปรแกรม เหตุการณ์การดึงข้อมูลที่ถูกดักจับสำหรับการโหลดหน้าเว็บนั้น คุณอาจพิจารณาการแคชด้วย ที่โหลดไว้แล้ว (แต่ไม่จำเป็นหาก เนื้อหามีการแคชล่วงหน้าอยู่แล้ว) ส่ง รายการ URL ที่จะแคชตัวอย่างสำหรับโปรแกรมทำงานของบริการด้านบนแสดงวิธีการใช้งาน นี้

Service Worker เริ่มควบคุมหน้านี้แล้ว controlling

เมื่อติดตั้ง Service Worker ใหม่และเริ่มควบคุมหน้าเว็บแล้ว เหตุการณ์การดึงข้อมูลครั้งต่อๆ ไปทั้งหมดจะผ่าน Service Worker นั้น หาก Service Worker จะเพิ่มตรรกะพิเศษในการจัดการเหตุการณ์การดึงข้อมูล คือเมื่อคุณทราบว่าตรรกะจะทำงาน

โปรดทราบว่าครั้งแรกที่คุณติดตั้งโปรแกรมทำงานของบริการ จะ ไม่เริ่มควบคุมหน้าปัจจุบัน เว้นแต่โปรแกรมทำงานของบริการนั้น โทร clients.claim() ในเหตุการณ์การเปิดใช้งาน ค่าเริ่มต้น คือรอจนกว่าการโหลดหน้าเว็บถัดไปจะเริ่มควบคุม

จากมุมมองของ workbox-window ค่านี้หมายความว่า ระบบจะส่งเหตุการณ์ controlling เฉพาะกรณีที่เหตุการณ์ Service Worker โทรหา clients.claim() กิจกรรมนี้ไม่ใช่ ส่งหากมีการควบคุมหน้าเว็บก่อนการลงทะเบียน

โปรแกรมทำงานของบริการได้เปิดใช้งานเรียบร้อยแล้ว activated

ตามที่กล่าวไว้ข้างต้น ครั้งแรกที่โปรแกรมทำงานของบริการเสร็จสิ้น การเปิดใช้งานหน้าอาจ (หรืออาจไม่) ได้เริ่มควบคุมหน้าไปแล้ว

ด้วยเหตุนี้คุณจึงไม่ควร ฟังเหตุการณ์ปุ่มเปิดใช้งาน เพื่อรับรู้ว่าเมื่อใดที่โปรแกรมทำงานของบริการเป็นผู้ควบคุมหน้าเว็บ อย่างไรก็ตาม หาก คุณใช้ตรรกะในเหตุการณ์ที่ใช้งานอยู่ (ใน Service Worker) และคุณ จำเป็นต้องทราบเมื่อตรรกะนั้นเสร็จสมบูรณ์ เหตุการณ์ที่เปิดใช้งานจะช่วยให้คุณ ทราบเรื่องนี้

เมื่อพบ Service Worker เวอร์ชันอัปเดต

เมื่อโปรแกรมทำงานของบริการใหม่เริ่มติดตั้ง แต่เวอร์ชันที่มีอยู่ยังใช้อยู่ ที่ควบคุมหน้านี้ พร็อพเพอร์ตี้ isUpdate ของเหตุการณ์ต่อไปนี้ทั้งหมดจะ เป็น true

วิธีที่คุณตอบสนองในสถานการณ์นี้มักจะแตกต่างจาก เนื่องจากคุณต้องจัดการเวลาและวิธีการที่ผู้ใช้จะได้รับการอัปเดตนี้

ช่วงเวลาสำคัญ กิจกรรม การดำเนินการที่แนะนำ
มีการติดตั้งโปรแกรมทำงานของบริการใหม่ (อัปเดตโปรแกรมก่อนหน้านี้) installed

หากนี่ไม่ใช่การติดตั้ง Service Worker ครั้งแรก (event.isUpdate === true) หมายถึงแท็ก พบและติดตั้ง Service Worker แล้ว (ซึ่งเป็นเวอร์ชันอื่น จากปุ่มที่ควบคุมหน้านั้นๆ อยู่)

ซึ่งโดยทั่วไปหมายความว่าเว็บไซต์รุ่นใหม่ได้มีการทำให้ใช้งานได้แล้ว เซิร์ฟเวอร์ของคุณ และเนื้อหาใหม่ๆ อาจเพิ่งเสร็จสิ้นการแคชล่วงหน้า

หมายเหตุ: นักพัฒนาแอปบางรายใช้เหตุการณ์ installed เพื่อแจ้ง ว่ามีเว็บไซต์เวอร์ชันใหม่พร้อมใช้งาน อย่างไรก็ตาม ขึ้นอยู่กับ ไม่ว่าจะโทรหา skipWaiting() ใน Service Worker ที่กำลังติดตั้ง Service Worker ที่ติดตั้งไว้อาจทำงานหรือไม่ก็ได้ในทันที หากคุณ ควรโทรหา skipWaiting() หากควรแจ้งผู้ใช้ เมื่อโปรแกรมทำงานของบริการใหม่เปิดใช้งาน และหากคุณ อย่าโทรหา skipWaiting แต่ควรแจ้งแก่พวกเขา การอัปเดตที่รอดำเนินการในกิจกรรมที่รอดำเนินการ (ดูรายละเอียดเพิ่มเติมด้านล่าง)

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

หากโปรแกรมทำงานของบริการเวอร์ชันที่อัปเดตแล้วไม่เรียกใช้ skipWaiting() ขณะที่กำลังติดตั้ง อีเมลจะไม่ เปิดใช้งานจนกว่าหน้าเว็บทั้งหมดจะควบคุมโดย Service Worker ที่ทำงานอยู่ในปัจจุบัน ยกเลิกการโหลดแล้ว คุณอาจต้องการแจ้งให้ผู้ใช้ทราบว่ามีการอัปเดตพร้อมให้บริการ และจะมีผลในครั้งถัดไปที่ผู้ใช้เข้าชม

คำเตือน! เป็นเรื่องปกติที่นักพัฒนาซอฟต์แวร์จะแจ้งผู้ใช้ โหลดซ้ำเพื่อรับการอัปเดต แต่ในหลายกรณี การรีเฟรชหน้าจะไม่เป็นการเปิดใช้งานผู้ปฏิบัติงานที่ติดตั้งไว้ หาก ผู้ใช้รีเฟรชหน้าเว็บ และ Service Worker ยังรออยู่ เหตุการณ์ waiting จะเริ่มทำงานอีกครั้งและ พร็อพเพอร์ตี้ event.wasWaitingBeforeRegister จะเป็นจริง หมายเหตุ เรามีแผนที่จะปรับปรุงประสบการณ์นี้ในรุ่นต่อๆ ไป ติดตามปัญหา #1848

อีกตัวเลือกหนึ่งคือการแจ้งผู้ใช้และถามว่าต้องการได้รับ อัปเดตหรือรอต่อไป หากเลือกรับการอัปเดต คุณจะ ใช้ postMessage() เพื่อบอกให้ Service Worker ทำงาน skipWaiting() ดูสูตรขั้นสูง เช่น มีการโหลดหน้าซ้ำให้ผู้ใช้ เป็นต้น

Service Worker เริ่มควบคุมหน้านี้แล้ว controlling

เมื่อโปรแกรมทำงานของบริการที่อัปเดตแล้วเริ่มควบคุมหน้าเว็บ นั่นหมายความว่า เวอร์ชันของ Service Worker ที่กำลังควบคุมอยู่แตกต่างจากเวอร์ชัน เวอร์ชันที่ควบคุมเมื่อหน้าเว็บโหลด ในบางกรณี ก็อาจจะหมายถึงเนื้อหาที่มีการอ้างอิงโดย หน้าปัจจุบันไม่ได้อยู่ในแคชอีกต่อไป (และอาจไม่ได้อยู่ในเซิร์ฟเวอร์ด้วย) คุณอาจต้องแจ้งให้ผู้ใช้ทราบว่าบางส่วนของหน้า อาจทำงานไม่ถูกต้อง

หมายเหตุ: เหตุการณ์ controlling จะไม่เริ่มทำงาน หากคุณไม่ได้เรียกใช้ skipWaiting() ใน Service Worker

โปรแกรมทำงานของบริการได้เปิดใช้งานเรียบร้อยแล้ว activated เมื่อโปรแกรมทำงานของบริการที่อัปเดตเปิดใช้งานเสร็จแล้ว หมายความว่า ตรรกะที่คุณเคยเรียกใช้ใน activate ของ Service Worker มี เสร็จสมบูรณ์แล้ว หากมีสิ่งใดๆ ที่คุณต้องการถ่วงเวลาไว้จนกว่าตรรกะนั้นจะมีผล เสร็จสิ้นแล้ว ก็ถึงเวลาที่จะทำงาน

เมื่อพบ Service Worker ในเวอร์ชันที่ไม่คาดคิด

บางครั้งผู้ใช้จะเปิดเว็บไซต์ของคุณไว้ในแท็บเบื้องหลังเป็นเวลานาน พวกเขาอาจเปิดแท็บใหม่และไปที่เว็บไซต์ของคุณโดยไม่รู้ตัว มีเว็บไซต์ของคุณเปิดอยู่ในแท็บพื้นหลังอยู่แล้ว ในกรณีดังกล่าว ที่ไซต์จะทำงานพร้อมกันได้ 2 เวอร์ชัน และ จะนำเสนอปัญหาที่น่าสนใจบางอย่างแก่คุณในฐานะนักพัฒนาซอฟต์แวร์

ลองนึกถึงสถานการณ์ที่คุณมีแท็บ A ทำงานอยู่ เวอร์ชัน 1 ของเว็บไซต์และแท็บ B เวอร์ชัน 2 เมื่อโหลดแท็บ B แท็บ B จะเป็นตัวควบคุมโดยเวอร์ชันของบริการ ผู้ปฏิบัติงานที่ส่งด้วย v1 แต่หน้าเว็บแสดงผลโดยเซิร์ฟเวอร์ (ถ้าใช้ กลยุทธ์การแคชเครือข่ายเป็นอันดับแรก สำหรับคำขอการนำทาง) จะมีเนื้อหา v2 ทั้งหมดของคุณ

แต่นี่ไม่ใช่ปัญหาสำหรับแท็บ B เพราะเมื่อคุณเขียน v2 คุณก็รู้ว่าโค้ด v1 ทำงานอย่างไร อย่างไรก็ตาม อาจเป็น ของแท็บ A เนื่องจากโค้ด v1 ไม่สามารถคาดการณ์สิ่งที่ การเปลี่ยนแปลงโค้ด v2 ที่อาจเกิดขึ้น

workbox-window จะช่วยกระจายวงจรการทำงานเพื่อช่วยจัดการสถานการณ์เหล่านี้ เหตุการณ์เมื่อตรวจพบการอัปเดตจาก "ภายนอก" Service Worker ซึ่ง ภายนอกหมายถึงเวอร์ชันที่ไม่ใช่เวอร์ชัน Workbox ปัจจุบัน ลงทะเบียนอินสแตนซ์แล้ว

เมื่อใช้ Workbox v6 ขึ้นไป เหตุการณ์เหล่านี้จะมีค่าเท่ากับเหตุการณ์ที่บันทึกไว้ ข้างต้น ด้วยการเพิ่มพร็อพเพอร์ตี้ isExternal: true ในแต่ละเหตุการณ์ ออบเจ็กต์ หากเว็บแอปพลิเคชันต้องใช้ตรรกะเฉพาะในการจัดการกับ "ภายนอก" Service Worker คุณสามารถตรวจสอบพร็อพเพอร์ตี้นั้นในเครื่องจัดการเหตุการณ์

การหลีกเลี่ยงข้อผิดพลาดที่พบบ่อย

หนึ่งในฟีเจอร์ที่ Workbox มีประโยชน์มากที่สุดก็คือการบันทึกของนักพัฒนาซอฟต์แวร์ และ โดยเฉพาะอย่างยิ่งสำหรับ workbox-window

เราทราบดีว่าการพัฒนาด้วยโปรแกรมทำงานของบริการมักจะทำให้เกิดความสับสน ซึ่งไม่ใช่เรื่องที่คุณคาดหวังไว้ อาจเป็นเรื่องยากที่จะรู้สาเหตุ

ตัวอย่างเช่น เมื่อคุณทำการเปลี่ยนแปลง Service Worker และโหลดหน้าเว็บซ้ำ คุณอาจไม่เห็นการเปลี่ยนแปลงนั้นในเบราว์เซอร์ สาเหตุที่เป็นไปได้มากที่สุดคือ เป็น Service Worker ยังรอเปิดใช้งานอยู่

แต่เมื่อลงทะเบียน Service Worker กับคลาส Workbox คุณจะได้ ได้รับทราบเกี่ยวกับการเปลี่ยนแปลงสถานะอายุการใช้งานทั้งหมดใน Play Console ช่วยแก้ปัญหาเกี่ยวกับสาเหตุที่ทำให้สิ่งต่างๆ ไม่เป็นอย่างที่คุณคาดหวัง

คำเตือนของคอนโซลหน้าต่างงานสำหรับผู้ปฏิบัติงานที่รออยู่

นอกจากนี้ ข้อผิดพลาดที่พบบ่อยซึ่งนักพัฒนาแอปทำเมื่อใช้โปรแกรมทำงานของบริการเป็นครั้งแรกคือ เพื่อลงทะเบียน Service Worker ใน ผิดขอบเขต

เพื่อช่วยป้องกันไม่ให้เกิดเหตุการณ์เช่นนี้ ชั้นเรียน Workbox จะเตือนคุณหาก หน้าที่ลงทะเบียนโปรแกรมทำงานของบริการไม่ได้อยู่ในขอบเขตของโปรแกรมทำงานของบริการนั้น จะ เตือนคุณในกรณีที่ Service Worker ของคุณทำงานอยู่แต่ยังไม่ การควบคุมหน้านี้

คำเตือนของคอนโซลหน้าต่าง Workbox สำหรับผู้ปฏิบัติงานที่ไม่มีการควบคุม

การสื่อสารของ Windows to Service Worker

การใช้งาน Service Worker ขั้นสูงส่วนใหญ่จะเกี่ยวข้องกับการรับส่งข้อความจำนวนมากระหว่าง Service Worker และหน้าต่าง ชั้นเรียน Workbox ก็ช่วยเราในเรื่องนี้เช่นกันโดย จะระบุเมธอด messageSW() ซึ่งจะทำให้ postMessage() อินสแตนซ์ Service Worker ที่ลงทะเบียนแล้วและรอการตอบกลับ

แม้ว่าคุณจะส่งข้อมูลไปยัง Service Worker ในรูปแบบใดก็ได้ แต่รูปแบบที่แชร์ แพ็กเกจกล่องงานทั้งหมดคือออบเจ็กต์ที่มี 3 พร็อพเพอร์ตี้ (2 รายการหลังคือ ไม่บังคับ):

พร็อพเพอร์ตี้ จำเป็นหรือไม่ ประเภท คำอธิบาย
type มี string

สตริงที่ไม่ซ้ำกันซึ่งระบุข้อความนี้

ตามหลักแล้ว ประเภทจะเป็นตัวพิมพ์ใหญ่ทั้งหมดโดยมีขีดล่างคั่น คำ หากประเภทแสดงถึงการดำเนินการที่ต้องทำ ก็ควรจะเป็นคำสั่ง ในเวลาปัจจุบัน (เช่น CACHE_URLS) หากประเภทแสดงถึง ข้อมูลที่ถูกรายงาน ข้อมูลนี้ควรเป็นช่วงเวลาในอดีต (เช่น URLS_CACHED)

meta ไม่ string ใน Workbox ค่านี้จะเป็นชื่อของแพ็กเกจ Workbox ที่ส่ง เมื่อส่งข้อความให้ตัวเอง คุณสามารถละเว้นพร็อพเพอร์ตี้นี้หรือ ตั้งเป็นวิธีใดก็ได้ที่คุณต้องการ
payload ไม่ * ข้อมูลที่กำลังส่ง ซึ่งโดยปกติจะเป็นวัตถุ แต่ไม่จำเป็นต้องเป็น

ข้อความที่ส่งผ่านเมธอด messageSW() จะใช้ MessageChannel เพื่อให้ผู้รับ สามารถตอบสนองต่อพวกเขาได้ หากต้องการตอบกลับข้อความที่โทรได้ event.ports[0].postMessage(response) ใน Listener เหตุการณ์ข้อความ เมธอด messageSW() จะแสดงคำมั่นสัญญาว่าจะแก้ไข response ใดก็ตาม ที่คุณตอบกลับ

ต่อไปนี้เป็นตัวอย่างการส่งข้อความจากหน้าต่างไปยัง Service Worker และ ในการตอบกลับ โค้ดบล็อกแรกคือ Listener ข้อความใน Service Worker และบล็อกที่ 2 จะใช้คลาส Workbox เพื่อส่ง ข้อความและรอการตอบกลับ:

โค้ดใน sw.js:

const SW_VERSION = '1.0.0';

addEventListener('message', event => {
  if (event.data.type === 'GET_VERSION') {
    event.ports[0].postMessage(SW_VERSION);
  }
});

โค้ดใน main.js (ทำงานในหน้าต่าง):

const wb = new Workbox('/sw.js');
wb.register();

const swVersion = await wb.messageSW({type: 'GET_VERSION'});
console.log('Service Worker version:', swVersion);

การจัดการความไม่เข้ากันของเวอร์ชัน

ตัวอย่างด้านบนแสดงวิธีการตรวจสอบ Service Worker เวอร์ชันจากหน้าต่าง เราใช้ตัวอย่างนี้เนื่องจากเมื่อส่ง ไปมาระหว่างหน้าต่างกับโปรแกรมทำงานของบริการ ซึ่งเป็นสิ่งที่สำคัญ ที่ต้องทราบว่าโปรแกรมทำงานของบริการของคุณอาจไม่ได้ใช้รุ่นเดียวกัน ที่โค้ดของหน้าเว็บทำงานอยู่ และโซลูชันในการจัดการกับเรื่องนี้ จะแตกต่างกันไป ขึ้นอยู่กับว่าคุณแสดงหน้าเว็บแบบเครือข่ายเป็นอันดับแรกหรือไม่ หรือแบบใช้แคชเป็นหลัก

เครือข่ายก่อน

เมื่อแสดงเครือข่ายของหน้าเว็บเป็นอันดับแรก ผู้ใช้ของคุณจะได้รับ เวอร์ชันล่าสุดของ HTML จากเซิร์ฟเวอร์ของคุณ แต่ครั้งแรกที่ผู้ใช้ เข้าชมเว็บไซต์ของคุณอีกครั้ง (หลังจากที่คุณทำการอัปเดตแล้ว) HTML ที่ลูกค้าจะได้รับ เวอร์ชันล่าสุด แต่ Service Worker ที่ทำงานในเบราว์เซอร์ เวอร์ชันที่ติดตั้งก่อนหน้านี้ (อาจจะหลายเวอร์ชันกว่า)

คุณจำเป็นต้องเข้าใจความเป็นไปได้นี้เพราะถ้า JavaScript โหลด ตามหน้าเว็บเวอร์ชันปัจจุบัน จะส่งข้อความไปยัง รุ่นเก่าของ ของ Service Worker เวอร์ชันนั้นอาจไม่ทราบวิธีตอบสนอง (หรืออาจตอบสนองด้วย รูปแบบที่เข้ากันไม่ได้)

ดังนั้น ควรกำหนดเวอร์ชันโปรแกรมทำงานของบริการเสมอและตรวจสอบ เพื่อหาเวอร์ชันที่เข้ากันได้ก่อนที่จะทำงานสำคัญ

ตัวอย่างเช่น ในโค้ดข้างต้น หากเวอร์ชัน Service Worker แสดงผลตามเวอร์ชันดังกล่าว การเรียกใช้ messageSW() เก่ากว่าเวอร์ชันที่คาดไว้ โปรดรอสักครู่ จนกว่าจะพบการอัปเดต (ซึ่งควรเกิดขึ้นเมื่อคุณโทรหา register()) ที่ คุณสามารถแจ้งผู้ใช้หรือการอัปเดต ข้ามขั้นตอนการรอ เพื่อเปิดใช้งาน Service Worker ใหม่ทันที

แคชก่อน

ซึ่งต่างจากเวลาที่คุณแสดงหน้าเว็บที่เน้นเครือข่ายเป็นหลัก เมื่อแสดงหน้าแคช ก่อนอื่น คุณต้องรู้ว่า ในตอนแรกหน้าเว็บจะมีเวอร์ชันเดียวกับ Service Worker ของคุณ (เพราะนั่นคือหน้าที่ของ Service Worker) และด้วยเหตุนี้จึงมีความปลอดภัย เพื่อใช้ messageSW() ทันที

อย่างไรก็ตาม หากพบ Service Worker เวอร์ชันอัปเดตและเปิดใช้งานแล้ว เมื่อหน้าเว็บเรียกใช้ register() (กล่าวคือ คุณตั้งใจข้ามขั้นตอนการรอ) การส่งข้อความให้อีเมลอาจไม่ปลอดภัยอีกต่อไป

กลยุทธ์หนึ่งในการจัดการความเป็นไปได้นี้ก็คือการใช้รูปแบบการกำหนดเวอร์ชัน จะช่วยให้คุณสามารถแยกความแตกต่างระหว่างการอัปเดตที่ด่วนกับการอัปเดตที่ไม่เสียหาย และในกรณีของการอัปเดตด่วน คุณย่อมรู้ว่าการส่งข้อความถึง Service Worker แต่คุณต้องเตือนผู้ใช้ว่า และแนะนำให้โหลดซ้ำเพื่อรับการอัปเดต

ไม่ต้องรอตัวช่วย

แบบแผนการใช้งานทั่วไปสำหรับการรับส่งข้อความของ Windows to Service Worker คือการส่งข้อความ {type: 'SKIP_WAITING'} ข้อความเพื่อแนะนำโปรแกรมทำงานของบริการที่ติดตั้งอยู่แล้ว ข้ามขั้นตอนการรอ และเปิดใช้งาน

ตั้งแต่ Workbox v6 เป็นต้นไป คุณสามารถใช้เมธอด messageSkipWaiting() เพื่อส่ง {type: 'SKIP_WAITING'} ข้อความไปยัง Service Worker ที่กำลังรอที่เชื่อมโยงกับ การลงทะเบียน Service Worker ปัจจุบัน โมเดลจะไม่ดำเนินการใดๆ ถ้าไม่มีการตั้งค่า กำลังรอโปรแกรมทำงานของบริการ

ประเภท

Workbox

คลาสที่ช่วยจัดการการลงทะเบียน การอัปเดต และของโปรแกรมทำงานของบริการ การตอบสนองต่อเหตุการณ์ในวงจรของโปรแกรมทำงานของบริการ

พร็อพเพอร์ตี้

  • เครื่องมือสร้าง

    เป็นโมฆะ

    สร้างอินสแตนซ์ Workbox ใหม่พร้อม URL ของสคริปต์และ Service Worker ตัวเลือก URL ของสคริปต์และตัวเลือกจะเหมือนกับที่ใช้เมื่อ ที่เรียกใช้ navigator.serviceWorker.register(scriptURL, ตัวเลือก)

    ฟังก์ชัน constructor มีลักษณะดังนี้

    (scriptURL: string | TrustedScriptURL, registerOptions?: object) => {...}

    • scriptURL

      string | TrustedScriptURL

      สคริปต์ Service Worker ที่เชื่อมโยงกับอินสแตนซ์นี้ การใช้ รองรับ TrustedScriptURL

    • registerOptions

      ออบเจ็กต์ไม่บังคับ

  • ใช้งาน

    Promise&lt;ServiceWorker&gt;

  • กำลังควบคุม

    Promise&lt;ServiceWorker&gt;

  • getSW

    เป็นโมฆะ

    แก้ไขด้วยการอ้างอิงไปยัง Service Worker ที่ตรงกับ URL ของสคริปต์ ของอินสแตนซ์นี้ทันทีที่พร้อมให้ใช้งาน

    หากมีบริการที่ใช้งานอยู่หรือกำลังรอดำเนินการแล้ว ณ เวลาลงทะเบียน ที่มี URL ของสคริปต์ตรง จะถูกนำมาใช้ (โดยต้องรอ Service Worker มีความสำคัญเหนือกว่า Service Worker ที่ใช้งานอยู่หากทั้ง เนื่องจาก Service Worker ที่รออยู่จะมีการลงทะเบียนมากกว่า เมื่อเร็วๆ นี้) หากไม่มี Service Worker ที่ทำงานอยู่หรือกำลังรอจับคู่ในขณะลงทะเบียน สัญญาจะไม่ได้รับการแก้ไขจนกว่าจะพบและเริ่มต้นการอัปเดต โดยจะติดตั้งโปรแกรมทำงานของบริการ ณ จุดใด

    ฟังก์ชัน getSW มีลักษณะดังนี้

    () => {...}

    • returns

      Promise&lt;ServiceWorker&gt;

  • messageSW

    เป็นโมฆะ

    ส่งออบเจ็กต์ข้อมูลที่ส่งผ่านไปยัง Service Worker ที่ลงทะเบียนโดย อินสแตนซ์ (ผ่าน workbox-window.Workbox#getSW) และแก้ไข พร้อมคำตอบ (หากมี)

    คุณสามารถตั้งค่าการตอบกลับในตัวแฮนเดิลข้อความในตัวทำงานของบริการได้โดยดำเนินการดังนี้ จะโทรหา event.ports[0].postMessage(...) ซึ่งจะเป็นไปตามสัญญา messageSW() ส่งคืน ถ้าไม่ได้กำหนดการตอบสนองไว้ สัญญาจะ แก้ไข

    ฟังก์ชัน messageSW มีลักษณะดังนี้

    (data: object) => {...}

    • ข้อมูล

      ออบเจ็กต์

      ออบเจ็กต์ที่จะส่งไปยัง Service Worker

    • returns

      สัญญา<ไม่จำกัด>

  • messageSkipWaiting

    เป็นโมฆะ

    ส่งข้อความ {type: 'SKIP_WAITING'} ไปยัง Service Worker ที่ ขณะนี้อยู่ในสถานะwaitingที่เชื่อมโยงกับการจดทะเบียนปัจจุบัน

    หากไม่มีการลงทะเบียนปัจจุบันหรือไม่มี Service Worker อยู่ใน waiting การเรียกใช้จะไม่มีผล

    ฟังก์ชัน messageSkipWaiting มีลักษณะดังนี้

    () => {...}

  • รีจิสเตอร์

    เป็นโมฆะ

    ลงทะเบียน Service Worker สำหรับ URL และบริการของอินสแตนซ์นี้ ผู้ปฏิบัติงาน โดยค่าเริ่มต้น วิธีนี้จะหน่วงเวลาการลงทะเบียนจนกว่า หน้าต่างโหลดขึ้นมา

    ฟังก์ชัน register มีลักษณะดังนี้

    (options?: object) => {...}

    • ตัวเลือก

      ออบเจ็กต์ไม่บังคับ

      • ที่อยู่ติดๆ กัน

        บูลีน ไม่บังคับ

    • returns

      Promise&lt;ServiceWorkerRegistration&gt;

  • อัปเดต

    เป็นโมฆะ

    ตรวจหาการอัปเดตของ Service Worker ที่ลงทะเบียน

    ฟังก์ชัน update มีลักษณะดังนี้

    () => {...}

    • returns

      คำสัญญา<โมฆะ>

WorkboxEventMap

พร็อพเพอร์ตี้

WorkboxLifecycleEvent

พร็อพเพอร์ตี้

  • isExternal

    บูลีน ไม่บังคับ

  • isUpdate

    บูลีน ไม่บังคับ

  • originalEvent

    กิจกรรม ไม่บังคับ

  • sw

    ServiceWorker ไม่บังคับ

  • เป้าหมาย

    WorkboxEventTarget ไม่บังคับ

  • ประเภท

    typeOperator

WorkboxLifecycleEventMap

พร็อพเพอร์ตี้

WorkboxLifecycleWaitingEvent

พร็อพเพอร์ตี้

  • isExternal

    บูลีน ไม่บังคับ

  • isUpdate

    บูลีน ไม่บังคับ

  • originalEvent

    กิจกรรม ไม่บังคับ

  • sw

    ServiceWorker ไม่บังคับ

  • เป้าหมาย

    WorkboxEventTarget ไม่บังคับ

  • ประเภท

    typeOperator

  • wasWaitingBeforeRegister

    บูลีน ไม่บังคับ

WorkboxMessageEvent

พร็อพเพอร์ตี้

  • ข้อมูล

    ใดๆ

  • isExternal

    บูลีน ไม่บังคับ

  • originalEvent

    กิจกรรม

  • ports

    typeOperator

  • sw

    ServiceWorker ไม่บังคับ

  • เป้าหมาย

    WorkboxEventTarget ไม่บังคับ

  • ประเภท

    "message"

เมธอด

messageSW()

workbox-window.messageSW(
  sw: ServiceWorker,
  data: object,
)

ส่งออบเจ็กต์ข้อมูลไปยัง Service Worker ผ่าน postMessage และแก้ไขด้วย คำตอบ (หากมี)

คุณสามารถตั้งค่าการตอบกลับในตัวแฮนเดิลข้อความในตัวทำงานของบริการได้โดยดำเนินการดังนี้ จะโทรหา event.ports[0].postMessage(...) ซึ่งจะเป็นไปตามสัญญา messageSW() ส่งคืน ถ้าไม่ได้กำหนดการตอบสนองไว้ สัญญาว่าจะไม่ แก้ไข

พารามิเตอร์

  • sw

    ServiceWorker

    Service Worker ที่จะส่งข้อความถึง

  • ข้อมูล

    ออบเจ็กต์

    ออบเจ็กต์ที่จะส่งไปยัง Service Worker

การคืนสินค้า

  • สัญญา<ไม่จำกัด>