深入浅出现代 JavaScript—service workers(1)

611 阅读3分钟

「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

本来想要继续更新 Notification 不过感觉感觉想要 Notification 需要先弄懂 Service workers 所以今天就先来聊一聊 Service workers

Service workers 还使你能够处理推送消息。现在,Service workers 是网络 worker 的一种类型,Service workers 运行在浏览器主线程以外的线程中。

因为 Service workers 的运行独立于其所关联的应用程序,所以即使在应用程序在后台或未打开,或者浏览器已关闭,Service workers 依旧可以接受到消息。

service workers 的主要用途是作为一个缓存代理,处理网络请求,并存储内容供离线使用,其次是处理推送消息,今天实例是消息推送。

service worker 在不使用的时候会变成空闲状态,并在下次需要的时候重新启动。

现在,如果有你需要跨重启持久化和重用的信息,那么service worker 可以与 IndexedDB数据库一起工作。

局限性

这个缓存是持久的,独立于浏览器缓存或网络状态。现在,由于 service workers 的强大功能,以及为了防止中间人攻击,为了避免泄漏用户与服务器的通信内容,service workers 只可用于通过 TLS 提供的安全资源,需要使用 HTTPS 协议。我们将使用 localhost 来测试 service works。

生命周期

  • register
  • install
  • activate

还有一些功能性的事件例如

  • push
  • fetch
  • sync

接下来我们通过实现离线应用,也就是使用 Service workers 将一些文件缓存起来,在离线情况下,依旧可以访问网站,以增强用户的体验。

屏幕快照 2021-11-05 下午7.19.40.png

通过实现离线应用,我们将进一步了解用 service workers 和相关 API 以及如何使用这些 API。为你的应用程序缓存资源将使内容在各种网络条件下都可以快速加载。

有两种具体的适合使用的缓存行为可以通过 service worker 来实现。 第一种类型的缓存是在安装时预先缓存资源。 例如有HTML、CCS、Javascript、图片等。并且这些资源在你的应用程序中是共享的,可以在 Web 应用程序第一次打开时,service workers 缓存这些资源。

检测浏览器是否支持 service Workers

if('serviceWorker' in navigator){
    console.log('Service Worker Supported');
}

注册 Service Workers

if('serviceWorker' in navigator){
    console.log('Service Worker Supported');
    window.addEventListener('load',function(){
        navigator.serviceWorker
            .register('../sw_cache_page.js')
            .then(reg => console.log(`Service Worker Registered`))
            .catch(err => console.error(err))
    })
}
Service Worker Supported
about.html:42 Live reload enabled.
main.js:6 Service Worker Registered

在可以在 application 页面中查看注册 service workers。

屏幕快照 2021-11-05 下午5.04.06.png

然后勾选 Update on reload,这样在刷新是重新加载 service workers。

屏幕快照 2021-11-05 下午5.06.07.png

self.addEventListener('install',()=>{
    console.log(`service worker: installed `)
});

self.addEventListener('activate',()=>{
    console.log(`service worker: activate `)
});

屏幕快照 2021-11-05 下午6.05.00.png

可以勾选 Offline 来模拟离线。

屏幕快照 2021-11-05 下午6.07.48.png

const cacheName = 'v1';

const cacheAssets = [
    'index.html',
    'about.html',
    '/css/style.css',
    '/js/main.js'
]

这里我们给缓存文件

self.addEventListener('install',(e)=>{
    console.log(`service worker: installed `);
    e.waitUntil(
        caches.
            open(cacheName)
            .then(cache=>{
                console.log(`service worker:caching files`)
            })
    )
})

调用 cache.addAll 可以将所有文件都缓存起来,可以在 Cache 下的 Cache Storage 下查看到缓存起来文件,现在

self.addEventListener('install',(e)=>{
    console.log(`service worker: installed `);
    e.waitUntil(
        caches.
            open(cacheName)
            .then(cache=>{
                console.log(`service worker:caching files`)
                cache.addAll(cacheAssets)
            })
            .then(()=>self.skipWaiting())
    )
})

屏幕快照 2021-11-05 下午6.39.04.png

不过现在还是无法在离线下访问到这些缓存起来页面。

下面我们先实现一下删除其他缓存版本,

self.addEventListener('activate',e =>{
    console.log(`service worker: activate `);
    e.waitUntil(
        catches.keys().then(cacheNames => {
            return Promise.all(
                cacheNames.map(cache=>{
                    if(cache != cacheName){
                        console.log('Service worker: clearing old cache');
                        return caches.delete(cache)
                    }
                })
            )
        })
    )
})