

Service Worker:让网页无网络也能访问
source link: https://www.kymjs.com/code/2017/02/15/01/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Service Worker:让网页无网络也能访问
题外话:写给所有移动端开发的同学:PWA(Progressive Web Apps) 一定是将来的移动开发趋势,且学且珍惜。
手机端可在我公众号【技术实验室】的历史推送文章查看。已经公开章节:
第一篇 · Service Worker:让网页无网络也能访问
第二篇 · PWA 程序开发实践
GitHub 演示项目 · PWAblog
Progressive Web Apps 比小程序还要方便,对于首次访问的用户可以直接在浏览器中进行访问,不需要安装应用。即使在比较糟糕的网络环境下,也能够快速地加载,且能够推送相关消息, 也可以像原生应用那样添加至桌面或浏览器主屏,能够有全屏浏览的体验。
PWA 和 Service Worker 是什么关系?Service Worker 是一个运行在浏览器后台进程里的js
,基于它可以实现消息推送,静默更新以及拦截和处理网络请求,包括可编程的响应缓存管理,是 PWA 的核心。
开源实验室 (https://www.kymjs.com) 已启用 Service Worker,现在只要你访问过的文章,在主流浏览器(包括PC、手机)二次访问均可离线访问啦。
Service worker 是一个完全独立于 Web 页面的 js 脚本,有他自己的生命周期。
每个 service worker 会对应一个缓存池,每个缓存池有多个缓存仓库。
首先讲讲它的声明周期,借用 Google 的一张图片:
若网站对应的 cacheName 没有 install
,则首先触发 install
事件。
若install
失败,则退出等待下次访问再启动;否则触发activate
事件。
在activate
中,判断当前页面是否在上文声明的 filesToCache 列表中,如果是则接管网页的显示。
接管网页以后,如果当前内存不足,会被杀死;否则等待处理fetch
和message
事件。这两个事件一个是当网络请求时,或者其他网页发出了消息时。 本文只讲如何让你的网页无网络也能访问,没有讲这两个事件,下一篇文章再给大家讲讲 service worker 深度使用。
从使用开始
首先你的站点必须支持https
(这也是为什么这两天你访问开源实验室出错的原因,在转全站 https)。
其次,你至少得懂一点 js
开发。
最后,你得有一个 52 或以上的版本的 Chrome 用作调试。
注册 Service Worker
首先,在你的网站根目录下创建一个 service-worker.js
文件(文件名自定)。
这个 service-worker.js 文件必须放在跟目录,因为 service workers 的作用范围是根据其在目录结构中的位置决定的。
然后需要检查浏览器是否支持 service workers,如果支持,就注册 service worker,将下面代码添加至网页要加载的js
中。
if('serviceWorker' in navigator) {
//注册上一步创建的js文件
navigator.serviceWorker
.register('/service-worker.js')
.then(function() { console.log('Service Worker Registered'); });
}
当用户访问一个注册了 service worker 的页面时,会触发一个叫install
事件,所以我们首先对这个事件监听。
var cacheName = 'oslab-kymjs-blog';
var filesToCache = [];
self.addEventListener('install', function(e) {
console.log('[ServiceWorker] Install');
e.waitUntil(
caches.open(cacheName).then(function(cache) {
console.log('[ServiceWorker] Caching app shell');
return cache.addAll(filesToCache);
})
);
});
当监听到install
事件以后,去缓存池打开名为 oslab-kymjs-blog 的缓存仓库。
每个 service worker 会对应一个缓存池,每个缓存池有多个缓存仓库。
只要缓存被打开,就调用 cache.addAll() 并传入一个 url 列表,然后加载这些资源并将响应添加至缓存。
有个注意事项要知道 cache.addAll() 方法中,如果某个文件下载失败了,那么整个缓存就会失败,service worker 的install
事件也将会失败。而如果install
失败了,那么接下来 service worker 就完全不会工作了。 所以一定要注意,文件列表一定不要太长了,越长造成失败的可能性就越高,每个要缓存的页面越大失败的可能性也越高。
用 Chrome Developer Tools 调试 Service Worker 非常方便。
首先 run 起你本地的 server(我博客是 jekyll 生成的,所以直接用了 jekyll 服务),然后 Chrome 右上角三个点,More Tools,Developer Tools。(mac快捷键 cmd+opt+i)
切换到 Application 视图
你应该能看到这样的一个页面
首次运行应该显示空的,看不到东西,刷新一下就可以了。但如果刷新后还是看不到,这意味着当前打开的页面没有已经被注册的 Service Worker,检查一下 注册 步骤的js
是否被加载了吧。
刷新前 注意勾选【update on reload】不然每次刷新都会起一个新的service worker,然后由于是串行执行,会等待前一个执行完,不然得手动点【skipWaiting】。
然后如果勾选了【update on reload】,可能会看到这个警告,无所谓,忽略它就好了。
删除无用缓存
当 service worker 开始启动时,就会触发 activate
事件。
所以我们监听 activate 在这里更新缓存。
self.addEventListener('activate', function(e) {
console.log('[ServiceWorker] Activate');
e.waitUntil(
caches.keys().then(function(keyList) {
return Promise.all(keyList.map(function(key) {
console.log('[ServiceWorker] Removing old cache', key);
if (key !== cacheName) {
return caches.delete(key);
}
}));
})
);
});
以上代码表示,如果执行到了 activate,首先判断现在缓存池中的缓存仓库 cacheName 是否和我们声明的 cacheName 同一个,如果不是,就清空缓存池中的无用缓存(install中下载新的缓存,activate 中删除旧缓存)。所以建议大家在 cacheName 的末尾加一个版本号,这样可以始终让service worker 加载最新的缓存。
至此,就为我们的博客完整接入了 service worker。
如果还不会,你可以以我博客的 service worker 做参考,看看我的写法 开源实验室防盗链。
最后,附上 Google 对 Service Worker 的介绍:an Introduction。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK