การใช้ปลั๊กอิน

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

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

ปลั๊กอิน Workbox ที่พร้อมใช้งาน

Workbox มีปลั๊กอินอย่างเป็นทางการต่อไปนี้สำหรับใช้ใน Service Worker ของคุณ

  • BackgroundSyncPlugin: หากคำขอเครือข่ายควรดำเนินการไม่สำเร็จ ปลั๊กอินนี้จะช่วยให้คุณสามารถเพิ่มลงในคิวการซิงค์เบื้องหลังเพื่อส่งคำขออีกครั้งเมื่อมีการทริกเกอร์เหตุการณ์การซิงค์ครั้งถัดไป
  • BroadcastUpdatePlugin: ให้คุณส่งข้อความในช่องทางออกอากาศหรือผ่าน postMessage() ทุกครั้งที่อัปเดตแคช
  • CacheableResponsePlugin: แคชเฉพาะคำขอที่ตรงตามเกณฑ์ที่ระบุเท่านั้น
  • ExpirationPlugin: จัดการจำนวนและอายุสูงสุดของรายการในแคช
  • RangeRequestsPlugin: ตอบสนองต่อคำขอที่มีส่วนหัวคำขอ HTTP Range

ปลั๊กอิน Workbox ไม่ว่าจะเป็นปลั๊กอินรายการใดรายการหนึ่งที่ระบุไว้ข้างต้นหรือปลั๊กอินที่กําหนดเอง จะใช้กับกลยุทธ์ Workbox ได้โดยการเพิ่มอินสแตนซ์ของปลั๊กอินลงในพร็อพเพอร์ตี้ plugins ของกลยุทธ์ ดังนี้

import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {ExpirationPlugin} from 'workbox-expiration';

registerRoute(
  ({request}) => request.destination === 'image',
  new CacheFirst({
    cacheName: 'images',
    plugins: [
      new ExpirationPlugin({
        maxEntries: 60,
        maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
      }),
    ],
  })
);

วิธีการสําหรับปลั๊กอินที่กําหนดเอง

ปลั๊กอิน Workbox ต้องใช้ฟังก์ชัน Callback อย่างน้อย 1 รายการ เมื่อคุณเพิ่มปลั๊กอินลงในกลยุทธ์ ฟังก์ชันการเรียกกลับจะทํางานโดยอัตโนมัติในเวลาที่เหมาะสม กลยุทธ์จะส่งข้อมูลที่เกี่ยวข้องกับคำขอและ/หรือการตอบกลับปัจจุบันของฟังก์ชัน Callback เพื่อให้ปลั๊กอินของคุณมีบริบทที่ต้องดำเนินการ ระบบรองรับฟังก์ชัน Callback ต่อไปนี้

  • cacheWillUpdate: เรียกใช้ก่อนใช้ Response เพื่ออัปเดตแคช ในวิธีการนี้ คุณจะเปลี่ยนคำตอบก่อนที่จะเพิ่มลงในแคชได้ หรือจะส่งกลับ null เพื่อหลีกเลี่ยงการอัปเดตแคชทั้งหมดก็ได้
  • cacheDidUpdate: เรียกใช้เมื่อมีการเพิ่มรายการใหม่ลงในแคชหรือมีการอัปเดตรายการที่มีอยู่ ปลั๊กอินที่ใช้วิธีการนี้อาจมีประโยชน์เมื่อคุณต้องการดำเนินการหลังจากการอัปเดตแคช
  • cacheKeyWillBeUsed: เรียกใช้ก่อนใช้คําขอเป็นคีย์แคช กรณีนี้เกิดขึ้นสำหรับทั้งการค้นหาแคช (เมื่อ mode คือ 'read') และการเขียนแคช (เมื่อ mode คือ 'write') การเรียกกลับนี้มีประโยชน์หากคุณต้องการลบล้างหรือทำให้ URL เป็นมาตรฐานก่อนที่จะใช้เพื่อเข้าถึงแคช
  • cachedResponseWillBeUsed: ฟังก์ชันนี้จะเรียกใช้ก่อนใช้การตอบกลับจากแคช ซึ่งจะช่วยให้คุณตรวจสอบการตอบกลับนั้นได้ ณ จุดนี้ คุณสามารถแสดงผลคำตอบอื่นหรือแสดงผล null ก็ได้
  • requestWillFetch: เรียกใช้เมื่อคําขอกำลังจะส่งไปยังเครือข่าย มีประโยชน์เมื่อคุณต้องเปลี่ยน Request ก่อนที่ข้อมูลจะส่งไปยังเครือข่าย
  • fetchDidFail: เรียกใช้เมื่อคําขอเครือข่ายไม่สําเร็จ ซึ่งส่วนใหญ่เกิดจากไม่มีการเชื่อมต่อเครือข่าย และจะไม่ทํางานเมื่อเบราว์เซอร์มีการเชื่อมต่อเครือข่าย แต่ได้รับข้อผิดพลาด (เช่น 404 Not Found)
  • fetchDidSucceed: มีการเรียกใช้ทุกครั้งที่คำขอเครือข่ายดำเนินการสำเร็จ โดยไม่คำนึงถึงรหัสการตอบกลับ HTTP
  • handlerWillStart: เรียกใช้ก่อนที่ตรรกะตัวแฮนเดิลจะเริ่มทํางาน ซึ่งมีประโยชน์ในกรณีที่คุณต้องตั้งค่าสถานะตัวแฮนเดิลเริ่มต้น เช่น หากต้องการทราบระยะเวลาที่ตัวแฮนเดิลใช้ในการสร้างการตอบกลับ คุณสามารถจดบันทึกเวลาเริ่มต้นในการเรียกกลับนี้
  • handlerWillRespond: เรียกใช้ก่อนที่เมธอด handle() ของกลยุทธ์จะแสดงผลลัพธ์ ซึ่งจะมีประโยชน์ในกรณีที่คุณต้องแก้ไขผลลัพธ์ก่อนที่จะแสดงผลลัพธ์นั้นใน RouteHandler หรือตรรกะที่กำหนดเองอื่นๆ
  • handlerDidRespond: เรียกใช้หลังจากที่เมธอด handle() ของกลยุทธ์แสดงผล ในกรณีนี้ การบันทึกรายละเอียดคำตอบสุดท้ายอาจมีประโยชน์ (เช่น หลังจากมีการเปลี่ยนแปลงโดยปลั๊กอินอื่นๆ)
  • handlerDidComplete: เรียกใช้หลังจากขยายระยะเวลาการรับประกันทั้งหมดที่เพิ่มลงในเหตุการณ์จากการเรียกใช้กลยุทธ์ได้รับ��ารชำระแล้ว ซึ่งมีประโยชน์ในกรณีที่คุณต้องรายงานข้อมูลที่ต้องรอจนกว่าตัวแฮนเดิลจะเสร็จสิ้นเพื่อคํานวณข้อมูลต่างๆ เช่น สถานะการตีผลแคช เวลาในการตอบสนองของแคช เวลาในการตอบสนองของเครือข่าย และข้อมูลอื่นๆ ที่เกี่ยวข้อง
  • handlerDidError: เรียกใช้หากตัวแฮนเดิลให้คําตอบที่ถูกต้องจากแหล่งที่มาใดๆ ไม่ได้ ซึ่งเป็นเวลาที่เหมาะที่สุดในการให้คําตอบสำรองแทนที่จะให้คําตอบที่ไม่ถูกต้อง

Callback ทั้งหมดนี้คือ async ดังนั้นจึงจะต้องใช้ await เมื่อเหตุการณ์แคชหรือการดึงข้อมูลไปถึงจุดที่เกี่ยวข้องสําหรับ Callback ที่เกี่ยวข้อง

หากปลั๊กอินใช้การเรียกกลับทั้งหมดข้างต้น โค้ดที่ได้จะเป็นดังนี้

const myPlugin = {
  cacheWillUpdate: async ({request, response, event, state}) => {
    // Return `response`, a different `Response` object, or `null`.
    return response;
  },
  cacheDidUpdate: async ({
    cacheName,
    request,
    oldResponse,
    newResponse,
    event,
    state,
  }) => {
    // No return expected
    // Note: `newResponse.bodyUsed` is `true` when this is called,
    // meaning the body has already been read. If you need access to
    // the body of the fresh response, use a technique like:
    // const freshResponse = await caches.match(request, {cacheName});
  },
  cacheKeyWillBeUsed: async ({request, mode, params, event, state}) => {
    // `request` is the `Request` object that would otherwise be used as the cache key.
    // `mode` is either 'read' or 'write'.
    // Return either a string, or a `Request` whose `url` property will be used as the cache key.
    // Returning the original `request` will make this a no-op.
    return request;
  },
  cachedResponseWillBeUsed: async ({
    cacheName,
    request,
    matchOptions,
    cachedResponse,
    event,
    state,
  }) => {
    // Return `cachedResponse`, a different `Response` object, or null.
    return cachedResponse;
  },
  requestWillFetch: async ({request, event, state}) => {
    // Return `request` or a different `Request` object.
    return request;
  },
  fetchDidFail: async ({originalRequest, request, error, event, state}) => {
    // No return expected.
    // Note: `originalRequest` is the browser's request, `request` is the
    // request after being passed through plugins with
    // `requestWillFetch` callbacks, and `error` is the exception that caused
    // the underlying `fetch()` to fail.
  },
  fetchDidSucceed: async ({request, response, event, state}) => {
    // Return `response` to use the network response as-is,
    // or alternatively create and return a new `Response` object.
    return response;
  },
  handlerWillStart: async ({request, event, state}) => {
    // No return expected.
    // Can set initial handler state here.
  },
  handlerWillRespond: async ({request, response, event, state}) => {
    // Return `response` or a different `Response` object.
    return response;
  },
  handlerDidRespond: async ({request, response, event, state}) => {
    // No return expected.
    // Can record final response details here.
  },
  handlerDidComplete: async ({request, response, error, event, state}) => {
    // No return expected.
    // Can report any data here.
  },
  handlerDidError: async ({request, event, error, state}) => {
    // Return a `Response` to use as a fallback, or `null`.
    return fallbackResponse;
  },
};
จะจัดการให้ทั้งหมด

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

การเรียกกลับของปลั๊กอินทั้งหมดจะส่งผ่านออบเจ็กต์ state ด้วย ซึ่งเป็นค่าเฉพาะของปลั๊กอินนั้นๆ และกลยุทธ์ที่ปลั๊กอินเรียกใช้ ซึ่งหมายความว่าคุณสามารถเขียนปลั๊กอินที่การเรียกกลับรายการหนึ่งสามารถทำงานแบบมีเงื่อนไขโดยอิงตามสิ่งที่การเรียกกลับรายการอื่นในปลั๊กอินเดียวกันทํา (เช่น คํานวณผลต่างระหว่างการเรียกใช้ requestWillFetch() กับ fetchDidSucceed() หรือ fetchDidFail())

ปลั๊กอินของบุคคลที่สาม

หากคุณพัฒนาปลั๊กอินและคิดว่ามีการใช้งานนอกโครงการ เราขอแนะนำให้คุณเผยแพร่ปลั๊กอินนั้นเป็นโมดูล ด้านล่างนี้คือรายการสั้นๆ ของปลั๊กอิน Workbox ที่ชุมชนให้ไว้

คุณอาจค้นหาปลั๊กอิน Workbox เพิ่มเติมที่ชุมชนให้ไว้ได้โดยค้นหาในที่เก็บข้อมูลของ npm

สุดท้าย หากคุณสร้างปลั๊กอิน Workbox ที่ต้องการแชร์ ให้เพิ่มworkbox-plugin คีย์เวิร์ดเมื่อเผยแพร่ หากต้องการ โปรดแจ้งให้เราทราบทาง Twitter @WorkboxJS