Service Work
Service workers 是一个在浏览器背后运行的脚步,独立于 web 页面,是一个注册在指定源和路径下的事件驱动 worker--可由脚本创建的后台任务,任务执行中可以向其创建者收发信息
它采用JavaScript控制关联的页面或者网站,拦截并修改访问和资源请求
注意: service worker的注册日志记录在Chrome浏览器中可以通过访问 chrome://serviceworker-internals 查看。
#
加载流程[图片来源 https://lavas-project.github.io/pwa-book/chapter04/3-service-worker-dive.html]
#
特点- 独立于网站运行: 运行在其他线程中,所以不会造成阻塞
- 无法操作DOM
- 只能使用 HTTPS 或者 localhost
- 可以拦截全站请求
- 完全异步,无法使用XHR和localStorage
- 独立上下文
- 作用域与页面路径相关
#
使用#
servicework.htmlservicework.html 注册 sw.js
<script> //实际对应ServiceWorkerRegistration.active var serviceWorker = navigator.serviceWorker.controller //判断是否支持servicework if ('serviceWorker' in navigator) { //注册sw scope 设置sw的作用域 navigator.serviceWorker.register('sw.js', { scope: './' }) .then((registration) => { console.log("register success"); }).catch((error) => { console.log("regist failure ", error) }); } //创建一个通知用于与sw 双向通信 const messageChannel = new MessageChannel(); //监听sw发送过来的信息 messageChannel.port1.onmessage = function (event) { console.log(`Response from the SW : ${event.data.command}`); } //向sw发送信息 serviceWorker.postMessage({ command: "connect"}, [messageChannel.port2]);
//注销sw function logOff(){ console.log("logoff"); navigator.serviceWorker.getRegistration("./").then((registration)=>{ if(registration){ console.log("unregister"); registration.unregister(); } }) }</script>
#
sw.jsself.addEventListener('install', function (event) { console.log("install", event) self.skipWaiting();// sw立即生效,并将之前的销毁})self.addEventListener('activate', function (event) { console.log("activate", event) //让没被控制的 clients(页面、workers) 受控, 否则要刷新页面才受控 self.clients.claim();})//用于向主线程发送信息的通道channel = nullself.addEventListener('message', function (event) { //获取主线程发送过来的信息 const data = event.data; if (data.command === "connect") { channel = event.ports[0]; //向主线程发送信息 channel.postMessage({ command: "accept" }); }})
//页面fetch 监听self.addEventListener('fetch', function (event) { console.log('Handling fetch event for', event.request.url); event.respondWith( caches.match(event.request).then(function (response) { if (response) { console.log('Found response in cache:', response); return response; } console.log('No response found in cache. About to fetch from network...'); return fetch(event.request).then(function (response) { console.log('Response from network is:', response); return response; }).catch(function (error) { console.error('Fetching failed:', error); throw error; }); }) );});
#
参考文档#
工具#
使用场景- 缓存
- 后台运算
- 消息通知