service-worker虽然已列入标准,但是支持的浏览器还是有限制,还有比较多的问题。

1. 生命周期

注册成功-------installing--------------> 安装成功(installed)(waiting) ---------activating----------> 激活成功 (activated)------> 销毁(redundant)
其中任何一个步骤失败都将进入销毁(redundant)
a. 注册:

调用 navigator.serviceWorker.register 方法,第一个参数是 service-worker对应的js文件, 第二个参数可选,scope是表示 service-worker 的作用域,最大的作用域就是 service-worker.js所在目录。

这2个参数都相对于origin目录,而不是项目根目录。

比如 https://mdn.github.io/sw-test/sw.js ,项目根目录是 https://mdn.github.io/sw-test/,路径应该写成 /sw-test/sw.js 而非 /sw.js.

不写scope默认就是最大的作用域,{scope: '/service-worker/foo/'} 表示service-worker只在foo目录下生效,一定要保证当前sw是最新的且没有被之前sw控制的页面,否则没效果。

  1. navigator.serviceWorker.('/service-worker/service-worker.js', {scope: '/service-worker/foo/'})
  2. .then(function (registration) {
  3. console.log('registration:',registration);
  4. })
  5. .catch(function (e) {
  6. console.error(e);
  7. })

b. 安装

注册成功后进入installing状态,这时会触发 install 事件, 在这个事件里面我们可以添加文件到缓存,如果不调用 skipWaiting 当前sw会在安装成功后进入waiting状态,直到所有页面都没有被旧的sw控制为止。

调用skipWaiting 将使当前sw直接进入 activating 状态。在开发调试时最好设置skipWaiting ,否则刷新页面新的sw一直处于waiting而不被使用。

  1. self.addEventListener('install', function (event) { // 监听worker的install事件
  2. self.skipWaiting();//让新 SW 立即激活。这里不会跳过 installing, 只会等安装成功后跳过 waiting直接将之前存在的sw销毁,新的sw进入到activating
  3. event.waitUntil( // 延迟install事件直到缓存初始化完成
  4. caches.open(CACHE_VERSION)
  5. .then(function (cache) {
  6. console.log('Opened cache');
  7. return cache.addAll(CACHE_FILES); // 会从网络加载需要缓存的文件,这时当前sw的fetch还没监听
  8. })
  9. );
  10. });

3. 激活

sw从waiting状态进入到 activating 这时会触发 activate 事件, 可以在这个事件里面处理缓存的清理功能,这里要注意 self.clients.claim ,假如页面没有sw控制,这个方法可以让当前页面马上sw控制,在控制之后的请求都会被fetch监听到,如果没有调用这个方法就必须刷新页面或关了页面重新进来页面才会被sw控制。

  1. self.addEventListener('activate', function (event) { // 监听worker的activate事件
  2.  
  3. event.waitUntil( // 延迟activate事件直 到
  4. caches.keys().then(function(keys){
  5. return Promise.all(keys.map(function(key, i){ // 清除旧版本缓存
  6. if(key !== CACHE_VERSION){
  7. //console.log(keys, key)
  8. return caches.delete(keys[i]);
  9. }
  10. }))
  11. })
  12. )
  13.  
  14. //When a service worker is initially registered, pages won't use it until they next load. The claim() method causes those pages to be controlled immediately.
  15. self.clients.claim(); //让没被控制的 clients(页面、workers) 受控, 否则要刷新页面才受控,比如资源加载触发fetch(可以设置延时加载模拟)
  16. });

激活成功后进入activated状态,这时fetch、message、put事件被触发。

  1. self.addEventListener('fetch', function(event) {
  2. // Do stuff with fetch events
  3. });
  4.  
  5. self.addEventListener('message', function(event) {
  6. // Do stuff with postMessages received from document
  7. });

可以利用fetch事件监听资源请求,进行修改响应或请求,发现请求资源没在缓存列表,可以从网络加载资源,并添加到缓存列表

  1. self.addEventListener('fetch', function (event) { // 截取页面的资源请求
  2. console.log('fetching',event.request); //网络请求触发该事件
  3. event.respondWith(
  4. caches.match(event.request).then(function (response) {
  5. if(res){ // 匹配缓存返回缓存中的资源
  6. return res;
  7. }else{
  8. throw new Error();
  9. }
  10. }).catch(function() { //没有在缓存列表,重新请求网络
  11. return fetch(event.request).then(function(response) {
  12. //if not a valid response send the error
  13. if(!response || response.status !== 200 || response.type !== 'basic'){
  14. return response;
  15. }
  16. return caches.open(CACHE_VERSION).then(function(cache) {
  17. cache.put(event.request, response.clone()); //请求的资源添加到缓存
  18. return response; //返回请求的响应
  19. });
  20. });
  21. }).catch(function() {
  22. //请求失败返回默认的资源
  23. return caches.match('/sw-test/gallery/myLittleVader.jpg');
  24. })
  25. );
  26. });

service worker 所涉及的知识比较多,包括cache缓存、promise等。

至于cache能缓存多大的容量,同一域名下的 ServiceWorkerCache 也只能使用 40M,参考:https://zhuanlan.zhihu.com/p/27586862

PWA的核心技术包括:

Web App Manifest – 在主屏幕添加app图标,定义手机标题栏颜色之类
Service Worker – 缓存,离线开发
App Shell – 先显示APP的主结构,再填充主数据,更快显示更好体验
Push Notification – 消息推送

可以参考百度的基于vue的pwa脚手架:https://lavas.baidu.com/

参考文档:

https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API/Using_Service_Workers

http://www.zhangxinxu.com/wordpress/2017/07/service-worker-cachestorage-offline-develop/

https://segmentfault.com/a/1190000006061528

https://segmentfault.com/a/1190000007487049#articleHeader2

https://zhuanlan.zhihu.com/p/20040372

service-worker实践的更多相关文章

  1. Service Worker

    Service Worker 随着前端快速发展,应用的性能已经变得至关重要,关于这一点大佬做了很多统计.你可以去看看. 如何降低一个页面的网络请求成本从而缩短页面加载资源的时间并降低用户可感知的延时是 ...

  2. 转《service worker在移动端H5项目的应用》

    1. PWA和Service Worker的关系 PWA (Progressive Web Apps) 不是一项技术,也不是一个框架,我们可以把她理解为一种模式,一种通过应用一些技术将 Web App ...

  3. service worker在移动端H5项目的应用

    1. PWA和Service Worker的关系 PWA (Progressive Web Apps) 不是一项技术,也不是一个框架,我们可以把她理解为一种模式,一种通过应用一些技术将 Web App ...

  4. service worker介绍

    原文:Service workers explained 译者:neal1991 welcome to star my articles-translator, providing you advan ...

  5. [PWA] 9. Service worker registerion && service work's props, methods and listeners

    In some rare cases, you need to ask user to refresh the browsser to update the version. Maybe becaus ...

  6. [PWA] 2. Service worker life cycle

    Once serive worker is registered, the first time we go to the app, we cannot see the logs from servc ...

  7. [PWA] 1. Intro to Service worker

    Service worker stays between our browser and noetwork requests. It can help to fetch data from cache ...

  8. Service Worker和HTTP缓存

    很多人,包括我自己,初看Service Worker多一个Cache Storage的时候,就感觉跟HTTP长缓存没什么区别. 例如大家讲的最多的Service Worker能让网页离线使用,但熟悉H ...

  9. Service Worker基础知识整理

    Service Worker是什么 service worker 是独立于当前页面的一段运行在浏览器后台进程里的脚本.它的特性将包括推送消息,背景后台同步, geofencing(地理围栏定位),拦截 ...

  10. Service Worker MDN英文笔记

    前言: 以前学习基础知识的时候总看别人写的入门文章,但有时候还是一脸懵逼,直到自己用心阅读了MDN的英文文档才对基础知识的一些理论有了更深的理解,所以我在边阅读文档的时候边记录下帮助比较大的,也方便大 ...

随机推荐

  1. JDBC连接数据库(Servlet+JSP)

    JDBC(Java Database connectivity),是连接数据库的一种方式.后面的框架Mybatis和Hibernate等都封装的是JDBC.在JDBC中常用的API有4个:Driver ...

  2. let和const命令整理

    一.let命令 基本用法 ES6 新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. for循环的计数器,就很合适使用let命令. for循环还 ...

  3. java.lang.ClassNotFoundException:org/apache/commons/collections/CursorableLinkedList

    明明有 commons-collections.jar 将jar包复制到Tomcat的WEB-INF/lib下就可以了...

  4. apache日志设置

    转自:http://hi.baidu.com/bxhack/item/71025d3e65987d88b611db5e apache日志存放位置 Windows: <Apache安装目录> ...

  5. LeetCode ZigZag Conversion(将字符串排成z字型)

    class Solution { public: string convert(string s, int nRows) { string a=""; int len=s.leng ...

  6. WIN7_X64连接远程Oracle数据库

    当使用微软提供的驱动:Provider=MSDAORA时,要使用32位的Oracle客户端,不然会报错! 下载:Oracle Database Instant Client 11g x86

  7. java Vamei快速教程16 RTTI

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 运行时类型识别(RTTI, Run-Time Type Identificatio ...

  8. cesium 加载shp格式的白模建筑

    ceisum加载shp格式的建筑.有两种思路,目前推荐第二种. 方法一:将shp格式转换为geojson格式,然后采用cesium提供的接口加载到ceisum中. 严重缺陷:在面对大场景问题,即数据量 ...

  9. 微信小程序(底部导航的实现)

    详情请看官方文档介绍: https://mp.weixin.qq.com/debug/wxadoc/dev/framework/config.html 在根目录配置文件app.json中配置底部导航: ...

  10. Bezier贝塞尔曲线的原理、二次贝塞尔曲线的实现

    Bezier曲线的原理 Bezier曲线是应用于二维图形的曲线.曲线由顶点和控制点组成,通过改变控制点坐标可以改变曲线的形状. 一次Bezier曲线公式: 一次Bezier曲线是由P0至P1的连续点, ...