ข้ามไปยังเนื้อหา

การ Register Service Worker

ก่อนที่ service worker จะดักจับ request ใด ๆ ได้ หน้าเว็บต้อง register service worker เสียก่อน การ register เป็นการบอก browser ว่าจะหาไฟล์ service worker ได้ที่ไหน และควรควบคุม URL ใดบ้าง

if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/sw.js')
.then((registration) => {
console.log('SW registered, scope:', registration.scope);
})
.catch((error) => {
console.error('SW registration failed:', error);
});
}

navigator.serviceWorker.register() คืนค่าเป็น Promise ที่ resolve ออกมาเป็น object ServiceWorkerRegistration property ที่สำคัญที่สุดบน object นั้นคือ scope

ควรครอบการเรียกด้วย 'serviceWorker' in navigator เสมอ browser ที่ไม่รองรับ service worker (browser รุ่นเก่ามาก ๆ บางตัว หรือหน้าเว็บที่เสิร์ฟผ่าน HTTP ธรรมดา) จะข้ามบล็อกนี้ไปเฉย ๆ อย่าปล่อยให้ API ที่หายไปทำให้หน้าเว็บของคุณพัง

scope เป็นตัวกำหนดว่า service worker ควบคุมหน้าและ sub-path ใดบ้าง โดยค่าเริ่มต้นคือไดเรกทอรีที่บรรจุไฟล์ service worker อยู่:

ตำแหน่งไฟล์ SWscope เริ่มต้นหน้าที่ถูกควบคุม
/sw.js/ทั้ง origin
/app/sw.js/app/เฉพาะ /app/ และที่อยู่ภายใต้นั้น
/shop/sw.js/shop/เฉพาะ /shop/ และที่อยู่ภายใต้นั้น

คุณสามารถจำกัด scope ให้แคบลงได้ (แต่ไม่สามารถขยายให้กว้างเกินไดเรกทอรีของไฟล์ SW ได้) โดยส่ง option scope เข้าไป:

navigator.serviceWorker.register('/sw.js', { scope: '/shop/' });

service worker จะทำงานได้บน secure origin เท่านั้น:

  • https:// — หน้า HTTPS ใด ๆ ใน production
  • http://localhost และ http://127.0.0.1 — ได้รับการยกเว้นอย่างชัดเจนสำหรับการพัฒนาในเครื่อง

การพยายาม register บน http:// ธรรมดา (ที่ไม่ใช่ localhost) จะล้มเหลวแบบเงียบ ๆ หรือโยน SecurityError ออกมา ควร deploy PWA ของคุณผ่าน HTTPS เสมอ

เดโมด้านล่างจะ register service worker แบบ minimal เปิดโปรเจกต์ StackBlitz แล้วดูที่ console ของ browser — คุณจะเห็น log ของการ register และ scope ของ SW

Runs a real service worker + manifest in your browser.
ตัวเลือกBenefitCost
Register service worker ตั้งแต่ตอน page loadcache และ offline support พร้อมใช้งานเร็วที่สุดเพิ่มงานให้ main thread ตอน load ครั้งแรกที่เป็นช่วงที่ user รอ critical content
Register หลัง load event (deferred)ไม่แย่ง resource กับ critical rendering path ตอนโหลดหน้าแรกผู้ใช้ที่ปิดหน้าเร็วเกินไปอาจไม่ทัน register เลยสักครั้ง
  • Register service worker path ที่ผิด scope ทำให้ควบคุมได้แค่บาง path แทนที่จะเป็นทั้งเว็บไซต์
  • ไม่ check if ('serviceWorker' in navigator) ก่อน register ทำให้ browser เก่าที่ไม่รองรับโยน error กลางหน้า
  • Register ซ้ำหลายครั้งโดยไม่ระวัง ทำให้เกิด service worker หลายเวอร์ชันแย่งกัน handle fetch event

💡 ตัวอย่างจากของจริง

web.dev checklist — แนะนำให้ register service worker หลัง load event เสมอ เพื่อไม่ให้แย่ง bandwidth กับ critical resource ตอนโหลดหน้าแรก

Twitter Lite — register service worker แบบ deferred ทำให้ time-to-interactive ของหน้าแรกไม่ถูกกระทบจากการติดตั้ง worker

navigator.serviceWorker.register() คืนค่าอะไร?
service worker สามารถ register ได้บน origin แบบใดบ้าง?
คุณวาง sw.js ไว้ที่ /admin/sw.js scope เริ่มต้นของตัวเองคืออะไร?
ทำไมจึงควรครอบการเรียก register ด้วย "serviceWorker" in navigator?