Service Worker初体验

作为一个临时救火做前端的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的工作流程,觉得非常不错。基本上说明了它是如何解决缓存问题的。

Service Worker

此图来自于codelabs.developers.google.com

转载于:https://my.oschina.net/u/3365822/blog/1543038

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值