ย้ายข้อมูลจาก Workbox v4 ไปยัง v5

คู่มือนี้มุ่งเน้นที่การเปลี่ยนแปลงที่ส่งผลกับส่วนอื่นของ Workbox v5 พร้อมด้วยตัวอย่างการเปลี่ยนแปลงที่คุณจำเป็นต้องทำเมื่ออัปเกรดจาก Workbox v4

การเปลี่ยนแปลงที่ส่งผลกับส่วนอื่นในระบบ

เปลี่ยนชื่อปลั๊กอินแล้ว

แพ็กเกจ Workbox v4 จำนวนหนึ่งมีคลาสชื่อ Plugin รวมอยู่ด้วย ใน v5 มีการเปลี่ยนชื่อคลาสเหล่านั้นเพื่อให้เป็นไปตามตัวระบุแพ็กเกจรูปแบบ + Plugin ดังนี้

  • BackgroundSyncPlugin
  • BroadcastUpdatePlugin
  • CacheableResponsePlugin
  • ExpirationPlugin
  • RangeRequestsPlugin

การเปลี่ยนชื่อนี้จะมีผลไม่ว่าคุณจะใช้คลาสผ่านการนำเข้าโมดูลหรือผ่านเนมสเปซ workbox.*

จุดแทนที่ไฟล์ Manifest ของ Precache เริ่มต้น

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

ใน Workbox v5 ตรรกะการแทนที่ได้เปลี่ยนแปลงไป และตอนนี้จะมีการใช้ self.__WB_MANIFEST เป็นจุดแทรกโดยค่าเริ่มต้น

// v4:
precacheAndRoute([]);

// v5:
precacheAndRoute(self.__WB_MANIFEST);

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

ตัวเลือก 2 รายการที่เคยรองรับสำหรับเส้นทางการนำทาง ได้แก่ blacklist และ whitelist เปลี่ยนชื่อเป็น denylist และ allowlist

ก่อนหน้านี้ workbox-routing รองรับเมธอด registerNavigationRoute() ซึ่งภายในได้ดำเนินการ 2 อย่างต่อไปนี้

  1. ตรวจพบว่าเหตุการณ์ fetch ที่ระบุมี mode เป็น 'navigate' หรือไม่
  2. หากเป็นเช่นนั้น ให้ตอบกลับคำขอนั้นโดยใช้เนื้อหาของ URL ที่ฮาร์ดโค้ดไว้ในแคชก่อนหน้านี้ โดยไม่คำนึงถึง URL ที่ไปยัง URL นั้น

นี่เป็นรูปแบบที่ใช้กันทั่วไปเมื่อใช้สถาปัตยกรรม App Shell

ขั้นตอนที่ 2 ซึ่งคือการสร้างการตอบกลับโดยการอ่านจากแคชจะไม่ตรงกับความรับผิดชอบของ workbox-routing แต่เรามองว่าเป็นฟังก์ชันที่ควรเป็นส่วนหนึ่งของ workbox-precaching ผ่าน createHandlerBoundToURL() ซึ่งเป็นเมธอดใหม่ วิธีการใหม่นี้สามารถใช้ได้กับคลาส NavigationRoute ที่มีอยู่ใน workbox-routing เพื่อให้ได้ตรรกะเดียวกัน

หากคุณใช้ตัวเลือก navigateFallback ในโหมด "สร้าง SW" ของเครื่องมือบิลด์ การสลับจะเกิดขึ้นโดยอัตโนมัติ หากคุณกำหนดค่าตัวเลือก navigateFallbackBlacklist หรือ navigateFallbackWhitelist ไว้ก่อนหน้านี้ ให้เปลี่ยนตัวเลือกเหล่านั้นเป็น navigateFallbackDenylist หรือ navigateFallbackAllowlist ตามลำดับ

หากใช้โหมด "แทรกไฟล์ Manifest" หรือเพียงเขียน Service Worker ด้วยตนเอง และ Service Worker v4 ของ Workbox จะเรียกใช้ registerNavigationRoute() โดยตรง คุณจะต้องแก้ไขโค้ดเพื่อรับการทำงานที่เทียบเท่ากัน

// v4:
import {getCacheKeyForURL} from 'workbox-precaching';
import {registerNavigationRoute} from 'workbox-routing';

const appShellCacheKey = getCacheKeyForURL('/app-shell.html');
registerNavigationRoute(appShellCacheKey, {
  whitelist: [...],
  blacklist: [...],
});

// v5:
import {createHandlerBoundToURL} from 'workbox-precaching';
import {NavigationRoute, registerRoute} from 'workbox-routing';

const handler = createHandlerBoundToURL('/app-shell.html');
const navigationRoute = new NavigationRoute(handler, {
  allowlist: [...],
  denylist: [...],
});
registerRoute(navigationRoute);

คุณไม่จำเป็นต้องโทรหา getCacheKeyForURL() อีกต่อไป เนื่องจาก createHandlerBoundToURL() จะจัดการให้คุณเอง

การนำ MakeRequest() ออกจาก workbox-strategies

การโทรไปยัง makeRequest() ส่วนใหญ่เทียบเท่ากับการโทรหา handle() ในคลาส workbox-strategy วิธีนี้มีความแตกต่างกันเล็กน้อยมากจนทำให้การดูทั้ง 2 แบบฟังดูสมเหตุสมผลแต่กลับไม่สมเหตุสมผล นักพัฒนาแอปที่เรียกใช้ makeRequest() ควรเปลี่ยนไปใช้ handle() ได้โดยไม่มีการเปลี่ยนแปลงเพิ่มเติม

// v4:
const strategy = new StaleWhileRevalidate({...});
const response = await strategy.makeRequest({event, request});

// v5:
const strategy = new StaleWhileRevalidate({...});
const response = await strategy.handle({event, request});

ใน v5 นั้น handle() จะถือว่า request เป็นพารามิเตอร์ที่จำเป็น และจะไม่กลับไปใช้ event.request ตรวจสอบว่าคุณส่งคำขอที่ถูกต้องเมื่อเรียกใช้ handle()

workbox-broadcast-update ใช้เสมอ postMessage()

ในเวอร์ชัน 4 ไลบรารี workbox-broadcast-update จะมีค่าเริ่มต้นเป็น Broadcast Channel API สำหรับส่งข้อความเมื่อมีการสนับสนุน และจะเปลี่ยนไปใช้ postMessage() เฉพาะเมื่อระบบไม่รองรับช่องออกอากาศเท่านั้น

เราตระหนักว่าการต้องคอยฟังแหล่งที่มา 2 แหล่งของข้อความขาเข้า ทำให้การเขียนโค้ดฝั่งไคลเอ็นต์มีความซับซ้อนมากเกินไป นอกจากนี้ ในบางเบราว์เซอร์ การเรียกpostMessage()จาก Service Worker ที่ส่งไปยังหน้าไคลเอ็นต์จะได้รับการบัฟเฟอร์โดยอัตโนมัติจนกว่าจะมีการตั้งค่า Listener เหตุการณ์ message Broadcast Channel API จะไม่มีการบัฟเฟอร์เลย และข้อความที่เพิ่งประกาศจะหายไปหากส่งก่อนที่หน้าไคลเอ็นต์จะพร้อมรับ

ด้วยเหตุนี้ เราจึงเปลี่ยน workbox-broadcast-update ให้ใช้ postMessage() ใน v5 เสมอ ระบบจะส่งข้อความทีละรายการไปยังหน้าเว็บของไคลเอ็นต์ทั้งหมดภายในขอบเขตของ Service Worker ปัจจุบัน

เพื่อรองรับลักษณะการทํางานใหม่นี้ คุณนําโค้ดที่มีอยู่ในหน้าไคลเอ็นต์ที่สร้างอินสแตนซ์ BroadcastChannel ออก และตั้งค่า Listener เหตุการณ์ message ใน navigator.serviceWorker แทนได้ ดังนี้

// v4:
const updatesChannel = new BroadcastChannel('api-updates');
updatesChannel.addEventListener('message', event => {
  const {cacheName, updatedUrl} = event.data.payload;
  // ... your code here ...
});

// v5:
// This listener should be added as early as possible in your page's lifespan
// to ensure that messages are properly buffered.
navigator.serviceWorker.addEventListener('message', event => {
  // Optional: ensure the message came from workbox-broadcast-update
  if (event.meta === 'workbox-broadcast-update') {
    const {cacheName, updatedUrl} = event.data.payload;
    // ... your code here ...
  }
});

ผู้ใช้ workbox-window ไม่ควรต้องทำการเปลี่ยนแปลงใดๆ เนื่องจากตรรกะภายในได้รับการอัปเดตแล้วเพื่อฟังการโทร postMessage() รายการ

เครื่องมือสร้างต้องใช้ Node.js v8 ขึ้นไป

ระบบไม่รองรับ Node.js เวอร์ชันก่อนหน้า v8 สำหรับ workbox-webpack-plugin, workbox-build หรือ workbox-cli อีกต่อไป หากใช้ Node.js เวอร์ชันก่อน 8 ให้อัปเดตรันไทม์เป็นเวอร์ชันที่รองรับ

workbox-webpack-plugin ต้องมี webpack v4 ขึ้นไป

หากคุณใช้ workbox-webpack-plugin ให้อัปเดตการตั้งค่า Webpack ให้ใช้ Webpack v4 เป็นอย่างต่ำ

ยกเครื่องตัวเลือกเครื่องมือการสร้าง

ระบบไม่รองรับพารามิเตอร์การกำหนดค่า workbox-build, workbox-cli และ workbox-webpack-plugin บางรายการอีกต่อไป ตัวอย่างเช่น generateSW จะสร้างกลุ่มรันไทม์ของ Workbox ในเครื่องให้คุณเสมอ ดังนั้นตัวเลือก importWorkboxFrom จะไม่สมเหตุสมผลอีกต่อไป

โปรดดูรายการตัวเลือกที่สนับสนุนในเอกสารของเครื่องมือที่เกี่ยวข้อง

การนำ generateSWString ออกจาก workbox-build

โหมด generateSWString ถูกนำออกจาก workbox-build แล้ว เราคาดว่าการเปลี่ยนแปลงนี้จะมีผลไม่มากนัก เนื่องจากมีการใช้ภายในโดย workbox-webpack-plugin เป็นหลัก

การเปลี่ยนแปลงที่ไม่บังคับ

การใช้การนำเข้าโมดูล

แม้ว่าการเปลี่ยนแปลงนี้จะ ก) ไม่บังคับ และ ข) เป็นไปได้ในทางเทคนิคเมื่อใช้ Workbox v4 แต่การเปลี่ยนแปลงที่คาดว่าจะมีมากที่สุดเมื่อเปลี่ยนไปใช้ v5 คือโมเดลที่ให้คุณสร้าง Service Worker แบบแพ็กเกจของคุณเองด้วยการนำเข้าโมดูลของ Workbox วิธีนี้เป็นทางเลือกในการเรียก importScripts('/path/to/workbox-sw.js') ที่ด้านบนของ Service Worker และการใช้ Workbox ผ่านเนมสเปซ workbox.*

หากใช้เครื่องมือบิลด์ใดเครื่องมือหนึ่ง (workbox-webpack-plugin, workbox-build, workbox-cli) ในโหมด "สร้าง SW" การเปลี่ยนแปลงนี้จะเกิดขึ้นโดยอัตโนมัติ เครื่องมือเหล่านี้ทั้งหมดจะแสดงผลแพ็กเกจรันไทม์ของ Workbox แบบกำหนดเองในเครื่องควบคู่กับโค้ดจริงที่จำเป็นต่อการใช้ตรรกะของโปรแกรมทำงานของบริการ ในสถานการณ์นี้จะไม่มีการพึ่งพา workbox-sw หรือสำเนา CDN ของ Workbox อีกต่อไป รันไทม์ของ Workbox จะแบ่งออกเป็นไฟล์แยกต่างหากซึ่งควรที่จะนำมาใช้งานพร้อมกับ Service Worker (เมื่อตั้งค่าเป็น false ซึ่งเป็นค่าเริ่มต้น) หรือรวมอยู่ในบรรทัดพร้อมกับตรรกะของโปรแกรมทำงานของบริการ (เมื่อตั้งค่าเป็น true) ทั้งนี้ขึ้นอยู่กับค่าของการกำหนดค่า inlineWorkboxRuntime

หากคุณกำลังใช้เครื่องมือสร้างในโหมด "แทรกไฟล์ Manifest" หรือไม่ได้ใช้เครื่องมือบิลด์ของ Workbox เลย คุณสามารถดูข้อมูลเพิ่มเติมเกี่ยวกับการสร้างกลุ่มรันไทม์ของกล่องงานของคุณเองได้ในคู่มือการใช้ Bundler (Webpack/Rollup) กับ Workbox

เราเขียนเอกสารประกอบและตัวอย่างสำหรับ v5 โดยสมมติว่าโมดูลนำเข้าไวยากรณ์ แม้ว่าเนมสเปซ workbox.* จะยังคงได้รับการรองรับใน Workbox v5 ต่อไป

การอ่านคำตอบที่เก็บไว้ล่วงหน้า

นักพัฒนาแอปบางรายต้องอ่านการตอบกลับที่แคชไว้ล่วงหน้าโดยตรงจากแคชแทนการใช้การตอบกลับโดยปริยายผ่านเมธอด precacheAndRoute() รูปแบบทั่วไปใน v4 คือการรับคีย์แคชเฉพาะสำหรับเวอร์ชันปัจจุบันของทรัพยากรที่แคชไว้ล่วงหน้า จากนั้นส่งต่อคีย์นั้นไปพร้อมกับชื่อแคชของแคชล่วงหน้าไปยัง caches.match() เพื่อรับ Response

เพื่อให้ขั้นตอนนี้ง่ายขึ้น workbox-precaching ใน v5 รองรับเมธอดใหม่ที่เทียบเท่า matchPrecache():

// v4:
import {cacheNames} from 'workbox-core';
import {getCacheKeyForURL} from 'workbox-precaching';

const cachedResponse = await caches.match(
  getCacheKeyForURL(`/somethingPrecached`),
  {
    cacheName: cacheNames.precache,
  }
);

// v5:
import {matchPrecache} from 'workbox-precaching';

const cachedResponse = await matchPrecache(`/somethingPrecached`);

การนำไปใช้ TypeScript

ใน v5 ไลบรารีรันไทม์ของ Workbox จะเขียนด้วย TypeScript แม้ว่าเราจะยังคงเผยแพร่โมดูลและแพ็กเกจ JavaScript ที่เปลี่ยนรูปแบบแล้วเพื่อรองรับนักพัฒนาซอฟต์แวร์ที่ไม่ได้ใช้ TypeScript แต่หากใช้ TypeScript คุณควรได้รับประโยชน์จากข้อมูลประเภทที่ถูกต้องและอัปเดตอยู่เสมอจากโปรเจ็กต์ Workbox โดยตรง

ตัวอย่างการย้ายข้อมูล

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

แม้ว่ากรณีนี้จะไม่ครอบคลุมการเปลี่ยนแปลงที่ส่งผลกับส่วนอื่นในระบบทั้งหมด แต่ต่อไปนี้คือก่อนและหลังการอัปเกรดไฟล์ Service Worker หนึ่งไฟล์จาก v4 เป็น v5 รวมถึงการเปลี่ยนเป็น TypeScript

การรับความช่วยเหลือ

เราคาดว่าการย้ายข้อมูลส่วนใหญ่จะตรงไปตรงมา หากพบปัญหาที่ไม่ได้กล่าวถึงในคู่มือนี้ โปรดแจ้งให้เราทราบโดยเปิดปัญหาใน GitHub