workbox-sw

โมดูล workbox-sw เป็นวิธีง่ายๆ ในการเริ่มต้นใช้งานโมดูล Workbox ทำให้การโหลดโมดูล Workbox ง่ายขึ้น และเสนอวิธีการช่วยเหลือแบบง่ายๆ

คุณสามารถใช้ workbox-sw ผ่าน CDN ของเรา หรือจะใช้กับชุดไฟล์เวิร์กบ็อกซ์บนเซิร์ฟเวอร์ของคุณเองก็ได้

การใช้ Workbox SW ผ่าน CDN

วิธีที่ง่ายที่สุดในการเริ่มใช้โมดูลนี้คือผ่าน CDN เพียงเพิ่มข้อมูลต่อไปนี้ไปยัง Service Worker

importScripts(
  'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
);

คุณจะมีเนมสเปซ workbox ในโปรแกรมทำงานของบริการซึ่งจะให้สิทธิ์เข้าถึงโมดูล Workbox ทั้งหมด

workbox.precaching.*
workbox.routing.*
etc

มีอะไรบางอย่างเกิดขึ้นเมื่อคุณเริ่มใช้โมดูลเพิ่มเติม

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

กำลังโหลดไลบรารีของ Workbox ในเครื่องมือสำหรับนักพัฒนาเว็บ

เบราว์เซอร์ของคุณแคชไฟล์เหล่านี้ไว้เพื่อให้ใช้งานได้แบบออฟไลน์ในอนาคต

การใช้ไฟล์ Workbox ในเครื่องแทน CDN

หากไม่ต้องการใช้ CDN คุณก็เปลี่ยนไปใช้ไฟล์ Workbox ที่โฮสต์ในโดเมนของตัวเองได้ง่ายๆ

วิธีที่ง่ายที่สุดคือรับไฟล์ผ่านคำสั่ง copyLibraries ของ workbox-cli แล้วบอกให้ workbox-sw ทราบว่าจะค้นหาไฟล์เหล่านี้ได้จากที่ใดผ่านตัวเลือกการกำหนดค่า modulePathPrefix

หากคุณวางไฟล์ไว้ใน /third_party/workbox-vX.Y.Z/ คุณจะใช้ไฟล์ดังนี้

importScripts('/third_party/workbox-vX.Y.Z/workbox-sw.js');

workbox.setConfig({
  modulePathPrefix: '/third_party/workbox-vX.Y.Z/',
});

หลีกเลี่ยงการนำเข้าแบบไม่พร้อมกัน

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

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

เช่น โค้ด Service Worker ระดับบนสุดต่อไปนี้ใช้งานได้

importScripts(
  'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
);

// This will work!
workbox.routing.registerRoute(
  ({request}) => request.destination === 'image',
  new workbox.strategies.CacheFirst()
);

แต่โค้ดด้านล่างอาจเป็นปัญหาหากคุณไม่ได้อ้างอิง workbox.strategies ที่อื่นใน Service Worker

importScripts(
  'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
);

self.addEventListener('fetch', event => {
  if (event.request.url.endsWith('.png')) {
    // Oops! This causes workbox-strategies.js to be imported inside a fetch handler,
    // outside of the initial, synchronous service worker execution.
    const cacheFirst = new workbox.strategies.CacheFirst();
    event.respondWith(cacheFirst.handle({request: event.request}));
  }
});

หากต้องการเขียนโค้ดที่อาจไม่เป็นไปตามข้อจำกัดนี้ คุณสามารถทริกเกอร์การเรียกใช้ importScripts() นอกตัวแฮนเดิลเหตุการณ์อย่างชัดแจ้งได้โดยใช้เมธอด workbox.loadModule() ดังนี้

importScripts(
  'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
);

// This will trigger the importScripts() for workbox.strategies and its dependencies:
workbox.loadModule('workbox-strategies');

self.addEventListener('fetch', event => {
  if (event.request.url.endsWith('.png')) {
    // Referencing workbox.strategies will now work as expected.
    const cacheFirst = new workbox.strategies.CacheFirst();
    event.respondWith(cacheFirst.handle({request: event.request}));
  }
});

อีกวิธีหนึ่งคือ คุณอาจสร้างการอ้างอิงไปยังเนมสเปซที่เกี่ยวข้องนอกตัวแฮนเดิลเหตุการณ์ แล้วใช้การอ้างอิงดังกล่าวในภายหลัง

importScripts(
  'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
);

// This will trigger the importScripts() for workbox.strategies and its dependencies:
const {strategies} = workbox;

self.addEventListener('fetch', event => {
  if (event.request.url.endsWith('.png')) {
    // Using the previously-initialized strategies will work as expected.
    const cacheFirst = new strategies.CacheFirst();
    event.respondWith(cacheFirst.handle({request: event.request}));
  }
});

บังคับให้ใช้บิลด์การแก้ไขข้อบกพร่องหรือเวอร์ชันที่ใช้งานจริง

โมดูล Workbox ทั้งหมดมาพร้อมกับบิลด์ 2 บิลด์ คือบิลด์การแก้ไขข้อบกพร่องซึ่งมีการบันทึกและการตรวจสอบประเภทเพิ่มเติม และบิลด์ที่ใช้งานจริงซึ่งบล็อกการบันทึกและการตรวจสอบประเภท

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

หากต้องการบังคับให้แก้ไขข้อบกพร่องหรือบิลด์ที่ใช้งานจริง คุณตั้งค่าตัวเลือกการกำหนดค่า debug ได้ดังนี้

workbox.setConfig({
  debug: true,
});

แปลงโค้ดโดยใช้คำสั่งการนำเข้าเพื่อใช้ workbox-sw

เมื่อโหลด Workbox โดยใช้ workbox-sw แพ็กเกจ Workbox ทั้งหมดจะเข้าถึงผ่านเนมสเปซ workbox.* ส่วนกลาง

หากมีตัวอย่างโค้ดที่ใช้คำสั่ง import ที่ต้องการแปลงไปใช้ workbox-sw ก็เพียงแค่โหลด workbox-sw แล้วแทนที่คำสั่ง import ทั้งหมดด้วยตัวแปรภายในที่อ้างอิงโมดูลเหล่านั้นในเนมสเปซส่วนกลาง

ซึ่งทำงานได้เนื่องจากแพ็กเกจ Workbox ของ Workbox ที่เผยแพร่ไปยัง npm ก็พร้อมใช้งานในเนมสเปซ workbox ส่วนกลางผ่านชื่อเวอร์ชัน camelCase ด้วย (เช่น โมดูลทั้งหมดที่ส่งออกจากแพ็กเกจ workbox-precaching npm จะอยู่ใน workbox.precaching.* และดูโมดูลทั้งหมดที่ส่งออกจากแพ็กเกจ workbox-background-sync npm ได้ที่ workbox.backgroundSync.*)

ต่อไปนี้คือตัวอย่างโค้ดที่ใช้คำสั่ง import ที่อ้างอิงโมดูลพื้นที่ทำงาน

import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {CacheableResponse} from 'workbox-cacheable-response';

registerRoute(
  ({request}) => request.destination === 'image',
  new CacheFirst({
    plugins: [new CacheableResponsePlugin({statuses: [0, 200]})],
  })
);

และนี่คือโค้ดเดียวกันที่เขียนขึ้นใหม่เพื่อใช้ workbox-sw (โปรดสังเกตว่ามีเพียงคำสั่งการนำเข้าเท่านั้นที่เปลี่ยนแปลงเท่านั้น และไม่ได้แก้ไขตรรกะ)

importScripts(
  'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
);

const {registerRoute} = workbox.routing;
const {CacheFirst} = workbox.strategies;
const {CacheableResponse} = workbox.cacheableResponse;

registerRoute(
  ({request}) => request.destination === 'image',
  new CacheFirst({
    plugins: [new CacheableResponsePlugin({statuses: [0, 200]})],
  })
);