最简单的 Service Worker,一看就懂

今天给我的项目搞了个PWA应用,网上的Service worker的资料非常复杂,如果你只是想要做一个简单的PWA应用,这篇文章是你最好的选择。

准备

你不需要vue,不需要npm!
你只需要一个代码编辑器,一个正常的浏览器(禁止使用IE😕),最好有一个Live server或者一个python(正常的版本)做服务器就够了!

开始

我相信你有一个index.html,一个js,对吧(如果没有,请去看别的文章)

注意:你的项目最好是静态的,不然会有一些困难

首先建一个minifest.json文件(名字不要错,不然浏览器的警告你受不了)
index.html<head>里写上

<link rel="manifest" href="manifest.json">

minifest.json

{
    "name": "名字",
    "short_name": "名字",
    "display": "standalone",
    "start_url": "/win12/index.html",
    "background_color": "#000",//加载时的背景(默认#fff)
    "icons": [
      {
        "src": "logo.png",//自己准备
        "sizes": "144x144",
        "type": "image/png"
      }
    ]
  }
  

以上这些都不重要,重要的在下面:

打开你的js文件,在末尾加上

navigator.serviceWorker.register('sw.js',{scope:'./'});

这是在将sw.js注册为一个serviceWorker,scope是它的作用域,这意味着如果sw.js在/win12/sw.js,那么作用域就不能是//win13

当然这样写会更 高端 全面

if('serviceWorker' in navigator){
	navigator.serviceWorker.register('sw.js',{scope:'./'});
}

当然,如果你现在还没有创建一个sw.js,就把它创建一下吧

基本功能

serviceWorker相当于一个海关,它可以审页面发出的所有请求,比如说页面请求style.css,sw就可以截下这个请求,然后给页面甩回去一个 404 别的响应
这个看起来很鸡肋,但是这还不是他的主要功能
它可以干什么呢?
它可以吧服务器的东西全部存到电脑上,等页面发出请求,就直接把电脑上的资源返回去
怎么样?高不高级?这就意味着,页面可以离线访问!

当然,如果你的项目不是静态,就只能将css、图片等存一下

怎么实现呢?很简单:

// sw.js
this.addEventListener('fetch', function (event) {
    event.respondWith(
      caches.match(event.request).then(res => {
        return res ||
          fetch(event.request)
            .then(responese => {
              const responeseClone = responese.clone();
              caches.open(version).then(cache => {
                cache.put(event.request, responeseClone);
              })
              return responese;
            });
      })
    )
});

很好理解,页面发请求电脑上有就直接返回,没有就找服务器

return res || //有就直接返回
	fetch(event.request)
	.then(responese => {
		const responeseClone = responese.clone();
		caches.open(version).then(cache => {
			//      ~~~~~~~
			//这里的version是版本号,具体后面会讲
			cache.put(event.request, responeseClone);
		});//没有就请求服务器然后再存在电脑上
	 	return responese;
	});

不需要详细理解

当然如果是动态,就要有选择性地存,不能把动态的页面也存了

// sw.js
this.addEventListener('install', function (event) {
	event.waitUntil(
		caches.open(version).then(function (cache) {
			return cache.addAll([
				'./style.css',
				'./script.js'
				//自己一个一个写吧,加油!
			]);
		})
	);
});

打开Live server或者python server(python -m http.server 8000)

这时候就要来看看浏览器怎么处置我们的sw了
devtool
在devtool的"应用程序"标签中(没有的点加号添加)的缓存存储中可以看到咱们sw存的东西了

如果你什么都没有看见----

点开清单标签,看看警告吧

这时候看到的v3.0.0是之前的version
这里就要谈一谈sw的更新机制了

更新

sw.js是不会把自己存在缓存里的,所以离线状态下管理缓存的是浏览器,当然这个就不是我们要管的了
缓存是一"组"一"组"的,比如v3.0.0就是这个组的名称,所以给项目的更新加上一个版本号是必须的,sw需要根据版本号判断是否需要更新。

这就意味着你如果在服务器上更改了内容,但没有改版本号,用户访问的网站将不会有任何更改。

更新电脑中的缓存很简单,只需要在sw.js中加上

let cacheNames = [version];
this.addEventListener('activate', function (event) {
    event.waitUntil(
        caches.keys().then(keys => {
            return Promise.all[keys.map(key => {
                if (!cacheNames.includes(key)) {
                    return caches.delete(key);
                }
            })]
        })
    );
});

事件activate会在pwa启动时触发
只要与当前版本不符,就删掉
很简单吧
这时sw.js大概长这样

let version='v3.0.0';

this.addEventListener('fetch', function (event) {
    event.respondWith(
      caches.match(event.request).then(res => {
        return res ||
          fetch(event.request)
            .then(responese => {
              const responeseClone = responese.clone();
              caches.open(version).then(cache => {
                cache.put(event.request, responeseClone);
              })
              return responese;
            });
      })
    )
});

let cacheNames = [version];
this.addEventListener('activate', function (event) {
    event.waitUntil(
        caches.keys().then(keys => {
            return Promise.all[keys.map(key => {
                if (!cacheNames.includes(key)) {
                    return caches.delete(key);
                }
            })]
        })
    );
});

测试

相信你的代码已经很完善了,接下来开始测试吧
打开你的网站,你应该看到这个

在这里插入图片描述
你可以试着断开网络,更改版本号,相信你的pwa可以正常地运行了!

通信

注意: sw.js 不能控制html元素,如果你想这样------看看下面

如果你需要在页面显示更新信息什么的,你就需要在页面与sw.js之间通信

页面->sw.js

页面 :

navigator.serviceWorker.controller.postMessage(
	"你好吗,sw.js?"
);

sw.js接收 :

this.addEventListener('message', function (event) {
  console.log(event.data);
});

很简单

sw.js->页面

在接收信息之后,要想回复,就这样

this.addEventListener('message', function (event) {
  event.source.postMessage('我很好');
});

页面接收

navigator.serviceWorker.addEventListener('message', function (e) {
  console.log(e.data);
});

当然,如果sw.js想要主动一点,也可以

this.clients.matchAll().then(client => {
  client[0].postMessage('不用问了,我很好');
})

注意了,因为sw.js独立于页面之外,如果在刷新时触发,信息会发到刷新前的页面
如果是在 启动/更新 时发送,页面还没有加载出来,所以this.clients会为空
所以这种情况可能需要加一个setTimeout或者等页面加载出来并发信息给sw.js后再回复

总结

高级吗?简单吗?
最后大家可以看一看这个示例 : Windows12 网页版

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值