โมดูล ES ใน Service Worker

ทางเลือกสมัยใหม่สําหรับ importScripts()

ข้อมูลเบื้องต้น

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

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

กรณีการใช้งาน

Use Case ที่เหมาะสําหรับโมดูล ES ภายใน Service Worker คือสําหรับการโหลดไลบรารีหรือโค้ดการกําหนดค่าสมัยใหม่ซึ่งแชร์กับรันไทม์อื่นๆ ที่รองรับโมดูล ES

การพยายามแชร์โค้ดด้วยวิธีนี้ก่อนมีโมดูล ES นั้นต้องใช้รูปแบบโมดูล "สากล" แบบเก่า เช่น UMD ซึ่งมีข้อมูลโค้ดซ้ำที่ไม่จำเป็น และการเขียนโค้ดที่ทําการเปลี่ยนแปลงตัวแปรที่แสดงทั่วโลก

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

ข้อจํากัดปัจจุบัน

การนําเข้าแบบคงที่เท่านั้น

คุณสามารถนําเข้าโมดูล ES ได้ 2 วิธี ดังนี้ แบบคงที่ ใช้ไวยากรณ์ import ... from '...' หรือแบบไดนามิก ใช้เมธอด import() ปัจจุบันระบบรองรับเฉพาะไวยากรณ์แบบคงที่ใน Service Worker

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

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

แล้วคนงานคนอื่นๆ ล่ะ

การรองรับโมดูล ES ในเวิร์กเกอร์ "เฉพาะ" ซึ่งสร้างขึ้นด้วย new Worker('...', {type: 'module'}) นั้นแพร่หลายกว่า และ Chrome และ Edge รองรับมาตั้งแต่เวอร์ชัน 80 รวมถึง Safari เวอร์ชันล่าสุด เวิร์กเกอร์เฉพาะรองรับทั้งการนําเข้าโมดูล ES แบบคงที่และแบบไดนามิก

Chrome และ Edge รองรับโมดูล ES ในเวิร์กเกอร์ที่แชร์มาตั้งแต่เวอร์ชัน 83 แต่ไม่มีเบราว์เซอร์อื่นที่รองรับในขณะนี้

ไม่รองรับแผนที่การนำเข้า

การแมปการนําเข้าช่วยให้สภาพแวดล้อมรันไทม์เขียนตัวระบุโมดูลใหม่ได้ เช่น ใส่ URL ของ CDN ที่ต้องการไว้ข้างหน้าเพื่อโหลดโมดูล ES ได้

แม้ว่า Chrome และ Edge เวอร์ชัน 89 ขึ้นไปจะรองรับแผนที่การนำเข้า แต่ปัจจุบันใช้ไม่ได้กับ Service Worker

การสนับสนุนเบราว์เซอร์

Chrome และ Edge รองรับโมดูล ES ใน Service Worker มาตั้งแต่เวอร์ชัน 91

Safari เพิ่มการรองรับในรุ่น Technology Preview 122 และนักพัฒนาแอปควรคาดหวังว่าฟังก์ชันนี้จะเปิดตัวใน Safari เวอร์ชันที่เสถียรในอนาคต

โค้ดตัวอย่าง

นี่เป็นตัวอย่างพื้นฐานของการใช้โมดูล ES ที่แชร์ในwindow บริบทของเว็บแอป พร้อมกับการลงทะเบียน Service Worker ที่ใช้โมดูล ES เดียวกัน

// Inside config.js:
export const cacheName = 'my-cache';
// Inside your web app:
<script type="module">
  import {cacheName} from './config.js';
  // Do something with cacheName.

  await navigator.serviceWorker.register('es-module-sw.js', {
    type: 'module',
  });
</script>
// Inside es-module-sw.js:
import {cacheName} from './config.js';

self.addEventListener('install', (event) => {
  event.waitUntil((async () => {
    const cache = await caches.open(cacheName);
    // ...
  })());
});

ความเข้ากันได้แบบย้อนหลัง

ตัวอย่างข้างต้นจะใช้งานได้หากเบราว์เซอร์ทั้งหมดรองรับโมดูล ES ใน Service Worker แต่ ณ เวลาที่เขียนนี้ ยังไม่มีเบราว์เซอร์ที่รองรับ

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

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

_รูปภาพโดย Vlado Paunovic ใน Unsplash_