service worker 实战

service worker 实战

service worker 是现代浏览器的一个新特性,伴随着谷歌的 PWA 概念一起,在近期广泛的出现在大家的视野里。

关于 service worker 的概念和相关的机制,本文不再介绍,大家可以参考 mdn 或自行 google。
本文主要说说我是怎么使用 service worker 的。

做什么?

service worker 故名意思,就是一个提供 service 的 worker。
通常 service worker 扮演着一个 proxy server,而目前因种种原因,我们主要是用它来做一个缓存代理。
最终,通过这个代理来加速我们 web 的加载,甚至是实现我们 web 的离线加载。

怎么做?

要通过 service worker 实现一个缓存代理其实很简单,借助谷歌的 sw-toolbox
这个库,简直可以说是分分钟搞定。以我的一个 h5 应用 为例:

  1. 首先创建一个 service worker 的脚本文件 sw.js
  2. 在脚本里引入 sw-toolbox importScripts('/static/js/lib/sw-toolbox.js');
  3. 为了 service worker 能尽快应用,分别在 install 事件中调用 self.skipWaiting,在 activate 事件中调用 self.clients.claim
  4. 针对应用的资源制定合适的缓存策略。
  5. 最后在页面中注册 service worker,即可。

完整 sw.js 代码如下:

var version = '1.2.0';

self.__uri = function(src) {
	return src
};

importScripts(__uri('/static/js/lib/sw-toolbox.js'));
importScripts(__uri('/static/js/lib/sw/monitor.js'));

self.addEventListener('install', function(event) {
	event.waitUntil(self.skipWaiting());
});
self.addEventListener('activate', function(event) {
	event.waitUntil(self.clients.claim());
});

toolbox.router.get('/:module/sw', toolbox.networkOnly);
toolbox.router.get('/static/(.*)', toolbox.cacheFirst);
toolbox.router.get('/(.*)', toolbox.networkFirst);
toolbox.router.get('/(.*)', function(request, values, options) {
	// 跨域,针对微信添加额外的头
	var newRequest = new Request(request, {
		headers: {}
	});
	return toolbox.cacheFirst.apply(this, [newRequest, values, options]);
}, {
	origin: /^https?:\/\/at\.alicdn\.com/,
	cache: {
		name: 'font_1457169990_5499172',
		maxEntries: 10,
		maxAgeSeconds: 60 * 60 * 24 * 7
	}
});

页面注册代码如下:

if (navigator.serviceWorker) {
	fetch(G.root + '/sw').then(function(res) {

		if (res.ok) {
			return res.json();
		}

		throw res.statusText;
	}).then(function(resData) {
		if (resData.data.on) {
			navigator.serviceWorker.register(__uri('/andyunjing/sw.js'));
		} else {
			navigator.serviceWorker.getRegistrations().then(function(registrations) {
				// console.log(registrations.scope)
				registrations.forEach(function(registration) {
					registration.unregister();
				});
			});
		}
	});
}

缓存策略

sw-toolbox 提供了 networkFirst、cacheFirst、fastest、cacheOnly、networkOnly 5种缓存应用策略,相信大家看名字也基本能猜到相应的逻辑了,具体的可查看官方文档了解。

在我的代码里面主要用到了 networkFirst、cacheFirst、networkOnly 这3种。

  • 针对 /:module/sw 这个开关接口请求,始终进行网络请求,即 networkOnly
  • 针对网页的静态资源,如果有缓存,则用缓存的,否则进行请求,即 cacheFirst
  • 针对网页的页面,为了获取最新的数据,首先从网络请求,但如果没网的话,也可以用缓存里面的页面,即 networkFirst

其他

在完整的代码里面,除了引入 sw-toolbox 库和配置缓存策略外,还有一些其他的东西,是我参考 https://zhuanlan.zhihu.com/p/25800461
这篇文章的经验,实现的服务器端的开关控制和相关的统计打点

还有一个就是跨域资源的加载,针对微信去掉 x-qid 的头,避免触发 options 请求。

效果

最终的页面,在首次加载的时候完成 service worker 的注册和启用,在第二次加载完成页面资源的缓存,然后第三次打开小伙伴们就能享受到网页秒开的爽快了!

service worker 作为一个渐进增强的选项,在不改动原有代码的情况下,通过简单的开发就是带来更好的体验,大家值得一试!

posted @ 2017-04-05 15:09  snadn  阅读(723)  评论(0编辑  收藏  举报