Service Worker là script chạy nền, tách khỏi trang, đóng vai proxy giữa ứng dụng và mạng.
// đăng ký từ trang
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
}
// sw.js — chặn và trả từ cache
self.addEventListener('install', (e) => {
e.waitUntil(caches.open('v1').then((c) => c.addAll(['/', '/app.css'])))
self.skipWaiting() // kích hoạt ngay, không chờ tab cũ đóng
})
self.addEventListener('activate', (e) => {
e.waitUntil(clients.claim()) // giành quyền kiểm soát tab đang mở
})
self.addEventListener('fetch', (e) => {
e.respondWith(
caches.match(e.request).then((hit) => hit ?? fetch(e.request)),
)
})Ràng buộc: chỉ chạy trên HTTPS (localhost được miễn), không truy cập DOM, và có vòng đời riêng install → waiting → activate → fetch.
Cho phép làm: chạy offline, chiến lược cache tuỳ biến, đồng bộ nền, push notification — đây là nền tảng kỹ thuật của PWA.
Lưu ý: service worker cũ rất dai. Bản mới mặc định nằm ở trạng thái waiting cho tới khi mọi tab của site đóng lại — nên deploy xong người dùng vẫn chạy bản cũ dù đã F5 nhiều lần. Đây là sự cố PWA phổ biến nhất, và skipWaiting() + clients.claim() ở trên là cách xử lý.
Lưu ý 2: cache sai chiến lược cho file HTML khiến người dùng kẹt ở bản cũ vĩnh viễn. Quy tắc an toàn: HTML dùng network-first, tài nguyên có hash trong tên dùng cache-first.