您的位置:首页 > 其它

Service Worker初体验

2017-09-25 00:00 411 查看
作为一个临时救火做前端的Java Server程序员,突然觉得浏览器强大的不要不要的。今天来总结一下一个比较酷的技术Service Worker。

项目中有一个web页面,需要加载很多静态资源,这些静态资源都是第三方提供的js,html等文件,总大小在3、4M左右。问题就出现了,每次客户打开页面时,加载时间实在太长。考虑到这些静态文件变更的频率不是很大,考虑用缓存解决。

传统的前端工程师提出了用Http协议中自带的缓存策略,即用
last-modified
e-tag
等header来解决。但需要Server端配置,在Reponse Header中加入这些字段。由于我们调用的是第三方的Server来获得静态资源,要求他们去改Server不太现实。

之前在Google大会上,看到他们一直在推PWA。其中很重要的一个概念就是离线访问,即在没有网路的情况下,也能将一个Web App启动起来,就如同本地App一样。实现的关键原理就是利用Service Worker和Cache API。关于PWA,这里就不做详细介绍了,本人也了解其中全部。这里只是借用其中的Cache API的部分(其实算是浏览器的API,PWA只是借用这些API来实现)。

Service Worker在当前主流浏览器中都有实现,而且恰巧我们项目只需要支持Chrome,就不用考虑浏览器兼容性的问题。

先说说Service Worker的声明周期

Registration

Service Worker开始注册,代码如下。其中
service-worker.js
就是Service Worker会执行的代码。这里要了解的是Service Worker和浏览器的JavaScript是在不同的线程中运行的。

if (window.navigator.serviceWorker) {
window.navigator.serviceWorker
.register('./service-worker.js')
.then(() => {
console.log('service worker registered');
})
.catch((error) => {
console.error(error);
});
}


Installation

self
就是一个Service Worker的句柄,用来调用Service Worker的方法。在这个阶段,可以预加载一些资源到Cache中。

const preCaches = [
'/',
'/login'
];

self.addEventListener('install', (event) => {
console.log('Service worker installing...');
event.waitUntil(
caches.open(cacheVersion)
.then((cache) => {
return cache.addAll(preCaches);
})
);
});


Activation

此阶段是激活一个Service Worker,可以用来执行清空之前版本缓存等操作。

self.addEventListener('activate', (event) => {
console.log('Service worker activating...');
event.waitUntil(async function() {
const keys = await caches.keys();
console.log(keys);
const result$ = keys
.filter((cacheName) => cacheVersion !== cacheName)
.map((cacheName) => caches.delete(cacheName));
return await Promise.all(result$);
}());
});

如果我们想监控并缓存一些请求信息,可以去监听Service Worker的
fetch
事件。这里可以把Service Worker当做一个请求代理。下面代码可以看到,我们只想缓存GET方法的结果,对于其他的请求,就忽略了。

self.addEventListener('fetch', (event) => {
const { url, method } = event.request;
console.log('Fetching:', event.request);
// we only want to cache GET method.
if (method === 'GET') {
event.respondWith(async function() {
const cache = await caches.open(cacheVersion);
let response = await cache.match(event.request);
if (response) {
console.log('cache found: ', url);
return response;
}
console.log('cache no found: ', url);
response = await fetch(event.request);
if (isCachable(event)) {
console.log('caching: ', url);
cache.put(event.request, response.clone());
}
return response;
}());
}
});

到这里就简单的实现了一个Service Worker和Cache使用。对于如何debug Service Worker,Chrome提供了很好的支持。有兴趣的同学可以去查查资料。其实Service Worker相关的知识还有很多,这里就不一一介绍了,以后时间会把项目中使用Service Worker遇到的问题和相关知识总结下来。

下图解释了Service Worker的工作流程,觉得非常不错。基本上说明了它是如何解决缓存问题的。



此图来自于codelabs.developers.google.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Service Worker Web