Service Worker - Progressive Web Apps

Service Worker可以理解为和某一网站相关联的一个在后台运行的线程,它专门为这个网站服务。它与当前网站线程独立,当网页崩溃时,它并不会受影响。

它可以实现的功能有:定期的后台同步,推送通知和缓存等。

Lifecycle

lifecycle

Fetch Event

sw.js在处理请求时,会出发fetch事件,可以通过监听该事件进行定制化处理,或拦截请求。


self.addEventListener('fetch', (e) => {
  console.log('fetch evetn:', e.request.url)
})

Service Worker Scope

/sw.js 一般来说应该放在根目录/。像/posts/sw.js 只在 /posts/ 下起作用。

下面的main.jssw.js注册在/posts下,只能在/posts下起作用。

// main.js
// Progressive Enhancement (SW supported)
// if ('serviceWorker' in navigator) {
if (navigator.serviceWorker) {
  // Register the SW
  navigator.serviceWorker.register('/sw.js', {scope: '/posts'}).then(function(registration){
    console.log('SW Registered');
  }).catch(console.log);
}

sw.js


// Service Worker
self.addEventListener('activate', () => {
  console.log('SW Active');
});

Service Wroker Registration

main.js

// Progressive Enhancement (SW supported)
// if ('serviceWorker' in navigator) {
if (navigator.serviceWorker) {

  // Register the SW
  navigator.serviceWorker.register('/sw.js').then(function(registration){
    registration.onupdatefound = () => {
      console.log("New SW Found");
      let newSW = registration.installing;

      newSW.onstatechange = () => {
        console.log(newSW.state);
      }
    };
  }).catch(console.log);

}

sw.js


// Service Worker
self.addEventListener('install', (e) => {
  e.waitUntil(new Promise((resolve) => {
    setTimeout(resolve, 5000);
  }))
});

self.addEventListener('activate', () => {
  console.log('SW2 Active');
});

Events:message

main.js


// Progressive Enhancement (SW supported)
if (navigator.serviceWorker) {

  // Register the SW
  navigator.serviceWorker.register('/sw.js').then(function(registration){
    if (registration.active) {
      registration.active.postMessage('respond to this');
    }
  }).catch(console.log);
  navigator.serviceWorker.addEventListener('message', (e) => {
    console.log(e.data);
  });

}

sw.js


// Service Worker

self.addEventListener('message', (e) => {
  // Respond to all clients
  self.clients.matchAll().then((clients) => {
    clients.forEach((client) => {

      // Only respond to sending client
      if (e.source.id === client.id) {
        client.postMessage("Private Hello from Service Worker");
      }
    });
  });
});

Events:push

push notification in browser.