service worker 的使用实例源代码

有很多面试题里面,有关于 service worker 的,比如说关于浏览器的缓存。

面试官问你,浏览器中的缓存位置有哪几种?你一搜,答案是:

浏览器中的缓存位置一共有四种:按优先级从高到第排列分别是:

  • Service Worker
  • MEmory Cache
  • Disk Cache
  • Push Cache

先不管其他的,我们先来看看 service worker 是个什么东西呢?请看官方文档

Service Worker API - Web API 接口参考 | MDN

Service worker 是一个注册在指定源和路径下的事件驱动 worker。它采用 JavaScript 文件的形式,控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源。你可以完全控制应用在特定情形(最常见的情形是网络不可用)下的表现。

重点是,使用 service worker 可以拦截并修改访问的资源请求,进而实现缓存资源。

还有一个场景可以使用 service worker,假设我们有一个A网站 https://a.com,如果这个网站由于某种原因被有关部门给封了,我们可以使用 service worker 拦截 A 网站的请求,然后重写网页内容。

使用 service worker

(1) 注册 service worker

在网站首页的 js 脚本中注册

try {
    if ('serviceWorker' in navigator) {
        navigator.serviceWorker.register('/sw.js', {
            scope: '/'
        });
    }
} catch (error) {
    console.error(`注册失败:${error}`);
}

(2)拦截响应

实现 sw.js 的代码

// 要展示给用户的新的页面代码
const newHtml = `


    
    
    
    
    


    
当前页面正在维护,
请前往 新网站
`; // 下载 service worker self.addEventListener('install', () => { self.skipWaiting(); console.log('service worker install'); }); // 监听 self.addEventListener('controllerchange', () => { console.log('service worker controllerchange'); if (refreshing) { return; } refreshing = true; window.location.reload(); }); // 监听所有的请求 self.addEventListener('fetch', async event => { try { // 拦截 document 类型 if (event.request.destination === 'document') { const finalResult = async () => { try { const fetchResponse = await fetch(event.request); const reader = fetchResponse.body.getReader(); // 使用可读流 const readerStream = new ReadableStream({ start(controller) { function push() { reader.read().then(({ done, value }) => { if (done) { controller.close(); return; } controller.enqueue(value); push(); }); } push(); } }); // 新建响应数据 const responseText = await new Response(readerStream, { headers: { 'Content-Type': 'text/html' } }).text(); // 响应内容不是自己的网站,替换响应内容 // 我们的网站 有一个 id 为 a-website-html-wrapper 的元素 if (responseText.indexOf('a-website-html-wrapper') < 0) { return new Response(newHtml, { headers: { 'Content-Type': 'text/html; charset=UTF-8' }, status: 200 }); } return new Response(responseText, { headers: { 'Content-Type': 'text/html; charset=UTF-8' }, status: 200 }); } catch (err) { // 离线也返回替代页面 return new Response(newHtml, { headers: { 'Content-Type': 'text/html; charset=UTF-8' }, status: 200 }); } }; event.respondWith(finalResult()); } } catch (error) { console.log('service worker', error); return new Response(responseText, { headers: { 'Content-Type': 'text/html; charset=UTF-8' }, status: 200 }); } });

你可能感兴趣的:(前端,javascript,service,worker)