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

288 阅读3分钟

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

注册 service workers

要安装一个 service workers,需要对其进行注册。注册目的是告诉浏览器 service workers 文件位置,然后浏览器就开始在后台安装 service workers。

这里可以项目下 index.html 文件中引用的 main.js 文件中引入sw_cache_page.js 文件

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))
    })
}

在代码中我们首先检查在 navigator 对象中是否有 serviceWorker 对象,然后调用 navigator.serviceWorker 对象的 register 方法来对 service workers 进行注册,该方法会返回一个 Promise 可以在成功安装 Service worker 进行一些处理。

然后用 registration.scope 来指定 service workers 的作用域。可以在每次页面加载时尝试注册一个 service workers。

而浏览器只有在第一次加载 service workers 或者更新了 service workers 才会进行注册。 service workers 的作用域用于指定 service workers 将从哪个路径拦截请求。默认作用域是 service workers 文件的路径,并扩展到其下面的所有目录。如果 service workers 脚本例如,serviceWorker.js 位于根目录中,服务工作者将控制来自该域的所有文件的请求。

如果在注册时设置了 /app/ 表示 service workers 将控制/app、/app/lower和/app/lower/lower等页面的请求。但是并不包括 app 目录以及位于其上层目录的页面的请求。

.register('../sw_cache_page.js',{
    scope:'/app/'
})

install(安装)事件

一旦浏览器成功地注册了一个 service worker,就会触发 install 事件。install 事件会在第一次安装 service worker 时被触发,或者页面检测到 service worker 代码发生变动也会触发 install 事件。可以在 install 事件回调中执行操作。对于缓存请求和资源的处理都可以在 install 事件来进行。

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())
    )
})

activate(激活)事件

安装成功后就会过渡到激活事件,service worker 将控制其作用域范围内加载的所有页面,并拦截相应的网络请求。在激活阶段可以将应用缓存就版本进行清除。

然而,您的应用程序中正在打开的页面将不在服务工作者的范围内。因为当页面被打开时,服务工作者并没有被加载。

要将当前打开的页面置于 service worker 的控制之下,你必须重新加载该页面或多个页面。在此之前,来自该页面的请求将绕过 service worker,并像平时一样操作。只要有依赖该特定版本的页面打开,service worker 就会保持控制。这确保了在任何时候只有一个版 本的服务工作者在运行。

如果一个新的 service worker 安装在有一个已经存在 service worker 的页面上,新的 srvice worker 将不会立即从原先的 service worker 手里接管这个页面,直到原有的 service worker 被删除,才能接管该页面。

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)
                    }
                })
            )
        })
    )
})

事件驱动

请注意,可以通过self.skipWaiting()以编程方式强制激活一个新的 service workers。

service workers 是事件驱动的。installl 和 activate 事件会引发相应的事件,service worker 可以对此作出响应。在 install 事件是应该为使用 service worker 做准备的时候,例如通过创建一个缓存并向其添加资源。activate 事件是清理旧的缓存和其他任何与 service workers 的先前版本相关的东西的好时机。serviceworker可以通过 message 事件接收来自其他脚本的信息。

对于 service worker 是事件驱动,除了上面介绍的 install

还有一些functional event(功能事件),如fetch、push 和 sync,service workers 可以对其作出响应。 要查看 service worers,请在浏览器的开发工具中,导航到 service worker。

self.addEventListener('fetch',e => {
    console.log('service Working:Fetching')
    e.respondWith(
        fetch(e.request).catch(()=> {
            caches.match(e.request);
        })
    )
})