Service worker
Bài đăng này đã không được cập nhật trong 5 năm
Chào mọi người, hôm nay chúng ta sẽ tìm hiểu về khái niệm Service worker 
Service worker
Service workerlà một script được browser(trình duyệt) chạy ngầm và tách biệt với trang web cài đặt nó
Service worker cung cấp những feature không cần tương tác với web page hay người dùng như :
- Xử lý những
network requests(cache responses) - Xử lý
push notification Background sync
Service worker không thể access trực tiếp vào DOM, thay vào đó, service worker giao tiếp với những pages được quản lý bằng việc response những message được gửi bởi postMessage, từ đó những pages này sẽ sửa đổi DOM theo yêu cầu
Hiện nay hầu hết các trình duyệt hiện nay đều đã hỗ trợ Service worker (trừ IE
)

Service worker life cycle
Lifecycle của service worker tách biệt với web page

Để install service worker cho trang web, đầu tiên cần register nó, việc register được thực hiện trong phần javascript ở trang web. Sau khi register thành công, browser sẽ tiến hành chạy ngầm bước install service worker
Khi install thành công sẽ tới bước activate, sau khi activated thành công, service worker sẽ quản lý tất cả các page nằm trong scope được register. Lúc này service worker sẽ xử lý những fetch hay message event xuất hiện khi có network request tới hay message được gửi từ web page
Register service worker
window.addEventListener('load', () => {
if('serviceWorker' in navigator) {
console.log('Service worker supported');
// Register service worker
console.log('Service worker register ...');
navigator.serviceWorker
.register('../service_worker_page.js')
.then(registration => console.log('Service worker registered') )
.catch(error => console.console.log('Register failed: ' + error) );
} else {
console.log('Service worker not supported');
}
});
Ở bước register, cần kiểm tra browser có hỗ trợ service worker hay không(trong biến navigator), sau đó register bằng serviceWorker object trong navigator, tham số truyền vào là đường dẫn tới file script service worker
Hàm register sẽ kiểm tra xem service worker đã được register hay chưa, nếu chưa thì mới tiến hành register, trả về một promise chứa biến registation(1 object của ServiceWorkerRegistration)
service worker scope phụ thuộc vào location nó được register, ở ví dụ trên là /service_worker_page.js, nghĩa là nó được register ở root của domain, lúc này service worker có thể nhận mọi fetch events trong toàn bộ domain.
Nếu service worker được register ở vị trí khác (e.g. /admin/sw.js) thì service worker chỉ có thể nhận fetch events trong những pages có url bắt đầu với /admin/index, /admin/users, ...
Install + Activate service worker
Như đã nói ở trên, sau khi register thành công, browser sẽ tiến hành chạy ngầm bước install service worker ở đoạn script được register, và bước activate được thực hiện ngay sau đó:
// service_worker_page.js
self.addEventListener('install', (e) => {
console.log('Service worker installed');
});
self.addEventListener('activate', (e) => {
console.log('Service worker activated');
});
self ở đây là 1 object của ServiceWorkerGlobalScope:
ServiceWorkerGlobalScope {clients: Clients, registration: ServiceWorkerRegistration, serviceWorker: ServiceWorker, onactivate: null, onfetch: null, …}
Sau khi activate service worker thành công, có thể kiếm tra lại trạng thái hoạt động của service worker:

Ta sẽ tìm hiểu kĩ hơn qua cơ chế caching của service worker:
Cache response
Một trong những feature của service worker chính là xử lý những network requests được gửi đi, cache response lại và sử dụng lại khi cần(tăng tốc độ load page, hiển thị dữ liệu được cache tới người dùng khi mất kết nối mạng (progessive web app))
Ở bước install service worker, những response(html, js, css) cần thiết sẽ được cache lại (trong CacheStorage):
var cacheName = 'static-assets-v1';
var cacheUrls = ['/', 'css/index.css', 'js/index.js'];
self.addEventListener('install', (e) => {
console.log('Service worker installed');
// Cache assets
e.waitUntil(caches.open(cacheName).then((cache) => {
cache.addAll(cacheUrls);
}));
});
cacheUrls chứa những request tới server muốn được cache lại, các response trả về từ server sẽ được cache lại trong CacheStorage:

Sau đó những network request được gửi đi (html, js, css, ...) sẽ trigger ra fetch event và được handle bởi service worker:
self.addEventListener('fetch', (e) => {
e.respondWith(caches.match(e.request).then((response) => {
if(response) {
// return response from cache
console.log(`request: ${e.request.url} - response: ${response}`);
return response;
}
// fetch new response from server
return fetch(e.request);
}));
});
Với những request (được lưu trong e.request) mà response đã được cache lại sẽ được trả thẳng về browser,
đối với những request mới sẽ được fetch mới tới server (ta cũng có thể cache những request mới này lại)
Ngay cả khi bị mất kết nối mạng, browser vẫn có thể hiển thị cho người dùng data được cache lại trước :
Vừa rồi là tìm hiểu của mình về Service worker, cảm ơn mọi người đã theo dõi 
All rights reserved
