service worker 是独立于当前页面的一段运行在浏览器后台进程里的脚本,它是一个独特的Web Worker。html
日常浏览器窗口中跑的页面运行的是主JavaScript线程,DOM和window全局变量都是能够访问的。Service Worker是走的另外的线程,能够理解为在浏览器背后默默运行的一个线程,或者说是独立于当前页面的一段运行在浏览器后台进程里的脚本。它脱离浏览器窗体,异步地运行在一个彻底独立的上下文环境,不会对主线程形成阻塞。在service worker中,window以及DOM都是不能访问的,但可使用PostMessage跟主进程进行通讯。前端
1.离线缓存(重点)依赖于cacheAPIvue
2.消息推送(重点)依赖于Google的推送服务,国内使用意义不大webpack
3.后台数据同步git
4.响应来自其它源的资源请求github
5.集中接收计算成本高的数据更新,好比地理位置和陀螺仪信息,这样多个页面就能够利用同一组数据web
6.在客户端进行CoffeeScript,LESS,CJS/AMD等模块编译和依赖管理(用于开发目的,一些在线编译网站)redis
7.后台服务钩子(基于推送)chrome
8.自定义模板用于特定URL模式编程
9.性能加强,好比预取用户可能须要的资源,好比相册中的后面数张图片
1.浏览器兼容性:不支持IE,可是因为是另一个线程,不影响在IE上使用。
使用ServiceWorker cache polyfill让旧版本浏览器支持 ServiceWorker cache API。
[浏览器兼容性](ww1.sinaimg.cn/large/007iU…)
2.https: Service Worker必须是https协议的,但本地环境下http://localhost或者http://127.0.0.1也能够的。
经过service worker能够劫持链接,伪造和过滤响应,为了不这些问题,只能在HTTPS的网页上注册service workers,防止加载service worker的时候不被坏人篡改。
Github Pages是HTTPS的,能够经过Github作一些尝试
3.service worker运行在它们本身的彻底独立异步的全局上下文中,也就是说它们有本身的容器。
4.service worker没有直接操做DOM的权限,可是能够经过postMessage方法来与Web页面通讯,让页面操做DOM。
5.service worker是一个可编程的网络代理,容许开发者控制页面上处理的网络请求。
6.浏览器可能随时回收service worker,在不被使用的时候,它会本身终止,而当它再次被用到的时候,会被从新激活。
7.service worker的生命周期是由事件驱动的而不是经过Client。
service worker拥有一个彻底独立于Web页面的生命周期
Service Worker生命周期的反应:installing → installed → activating → activated 'install'用来缓存文件,'activate'用来缓存更新
[Service Worker生命周期](pic.superbed.cn/item/5c8b19…)
注册service worker,在网页上生效
安装成功,激活 或者 安装失败(下次加载会尝试从新安装)
激活后,在sw的做用域下做用全部的页面,首次控制sw不会生效,下次加载页面才会生效
sw做用页面后,处理fetch(网络请求)和message(页面消息)事件 或者 被终止(节省内存)。
一、chrome://serviceworker-internals
[serviceworker-internals](ww1.sinaimg.cn/large/007i4…)
二、网页中Application
[Application1](ww1.sinaimg.cn/large/007iU…)
[Application2](ww1.sinaimg.cn/large/007i4…)
HTML 里面:
引进sw-demo-cache.js
webapck中的使用:
获取文件目录 引入第三个模块glob,递归获取打包后的文件目录。导出目录 经过webpack的DefinePlugin插件,导出上步获取的目录
web和service worker的通讯 经过postMessage实现web和service worker间的通讯
Service Worker的业界生态
Service Worker 主要在PWA中担任离线缓存应用技术的角色。
Webpack的offline-plugin, offline-plugin 能够把咱们的多页面应用进行缓存,即便这些html文件时独立的。它做为一个webpack插件使用,为咱们自动生成sw.js文件。
workbox:是sw-precache和sw-toolbox的继任者。它是一组内容库和工具,用于生成 Service Worker、预缓存、路由以及运行时缓存。另外,Workbox还附带模块,可轻松地将后台同步和Google analytics集成到 Service Worker。通俗来看,它能帮助开发人员下降Service Worker的使用成本,但目前没办法高效解决大型站点多团队多应用协做的问题。主要用于SPA。主要应用有淘宝最近分享的workbox3.0
lavas:是一套基于 Vue 的 PWA 解决方案,可以帮助开发者快速搭建 PWA 应用,解决接入 PWA 的各类问题,简单来看lavas = vue + pwa。它适用于新应用的开发,对于老应用使用PWA有必定成本,并且一样目前也没办法高效解决大型站点多团队多应用协做的问题。主要用于SPA。
开发人员接入只需两步:
在PWA管理平台填写相关配置,这些配置会存到redis集群。
在页面引入一小段js代码,这段代码在页面加载时执行,先向配置平台发出sw-reg.js请求,拉取配置,而后在页面注册sw。
为了提升sw可用性,管理平台设计时将sw与配置解耦。实际页面在零基础状况下应用PWA时会经历三次页面请求才能成功使用:
第一次页面请求注册sw并控制页面;
第二次页面请求拉取配置经过postmessage形式传给sw并存储在IndexedDB;
第三次页面请求时sw会拦截页面上全部http请求,根据配置执行相应的处理策略。
从框图中能够看到,sw将缓存存储在CacheStorage,数据和配置存储在IndexedDB。整个流程包括服务端和客户端都有报警监控,错误上报到cat。
整个平台设计与业务基本彻底解耦,要求业务在不接入PWA状况下也能正常使用,平台只是帮助业务在页面请求加载各个环节加强体验。
应用场景很普遍,一些应用到sw的站点:
百度、谷歌、腾讯、163网易、微博(m.weibo.cn/)、淘宝 PC 首页......
基本应用场景在手机端使用比较多,Web端也不少。
手机端应用得比较好的是mobile.twitter.com,在手机上的体验跟原生很接近。
Service Worker在咱们的项目中的应用:
咱们的设想是在离线的状况下,用户可以无感知的进行操做,而且在操做以后能把
操做对应的上传到服务器上……
为了达成这个目标,咱们须要使用SW在浏览器中作好缓存策略的选择:
对于某些固定不变的静态资源,咱们习惯在Service Worker初次安装的install事件中将其缓存,但资源过大或者网络不佳都会形成资源并未所有下载成功而致使Service Worker安装被中断,只有等下次用户在打开相应页面。这里能够将静态资源按优先级分为两类,一类是重要资源,一类是非重要资源,将重要资源放到安装等待队列中,非重要资源放到独立的队列中,这样只须要重要资源所有都加载成功就能够成功安装Service Worker了,能够提升Service Worker安装成功率。
对于在install中发现没有缓存,页面又依赖但又不常常变化的资源,能够在页面打开或发生用户交互时触发fetch而后使用fetch api再去网络拉取,将返回正常的response缓存起来以便下次使用。
在fetch事件中,仅去匹配资源,若匹配失败,表现出来的就是前端页面对于该 资源加载失败。这里容错性比较差,适合页面资源都是静态资源的,且不能使用不影响安装的资源预缓存。
在fetch事件中,仅将request从新抽出用fetch去网络加载并返回给前端页面。适用于资源大可能是动态资源、实时性要求高的场景。
简单的资源缓存中使用的就是缓存优先策略,先去缓存匹配,匹配失败折回网络,这算是最经常使用、容错性能好的一种策略。
在fetch事件中先去网络fetch,当出现服务器故障或者网络不良时,折回本地缓存,目的是为了展现最新的数据,对实时性要求比较高但又可以带来良好体验的应用,好比天气类型应用。
在fetch事件中同时发起本地缓存匹配及网络请求,谁先返回使用谁的,该方案适用于对性能要求比较高的站点,缩短了缓存优先策略中有可能缓存中没有资源再折回网络的时间消耗。
a. 首先保证跨域的资源来自安全的https地址;
b. 保证跨域资源服务器的response中Access-Control-Allow-Origin中包含当前的页面所在域或者为*;
c. 对于前端页面中的跨域资源的url能够附带“cors=1”参数,以便Service Worker在拦截以后能够判断出是跨域请求从而从新进行组装cors请求。
淘宝分享的WorkBox3.0实践中推荐使用的方案:
HTML,若是你想让页面离线能够访问,使用 NetworkFirst,若是不须要离线访问,使用 NetworkOnly,其余策略均不建议对 HTML 使用。
CSS 和 JS,状况比较复杂,由于通常站点的 CSS,JS 都在 CDN 上,SW 并无办法判断从 CDN 上请求下来的资源是否正确(HTTP 200),若是缓存了失败的结果,问题就大了。这种我建议使用 Stale-While-Revalidate 策略,既保证了页面速度,即使失败,用户刷新一下就更新了。
若是你的 CSS,JS 与站点在同一个域下,而且文件名中带了 Hash 版本号,那能够直接使用 Cache First 策略。
图片建议使用 Cache First,并设置必定的失效事件,请求一次就不会再变更了。
上面这些只是普适性的策略,见仁见智。还有,要牢记,对于不在同一域下的任何资源,绝对不能使用 Cache only 和 Cache first。