初探ServiceWorker

      最近接触了ServiceWorker的一些东西,整理了一些基本的东西。因为本人不是做JS开发所以对JS理解没有那么深,所以这篇文章是看了一些国外的博客,MDN后加了一些自己的理解,有些地方翻译的不是太准。

     参考资料:

         MDN:https://dbwriteups.wordpress.com/2015/11/16/service-workers-part-4-background-sync/

         ServiceWorkerDemo:https://github.com/riteshkumar078/serviceworker-offline-demo

         自己整理的ServiceWorker中文API:http://download.csdn.net/detail/qtstsq55/9453135

         国内翻译组:http://www.chinaw3c.org/archives/596/

      一个ServiceWorker是运行在浏览器后台的基本js脚本,它们不需要一个页面来支撑。它们异步地运行在一个完全独立的上下文环境,不会对主线程造成阻塞。ServiceWorker提供了一个Request/Response的代理机制,通过运行在后台的任务来丰富浏览器的离线体验。

      首先,我们可以通过ServiceWorker获得富离线操作。在ServiceWorker之前出现过AppCache技术,但是普遍反映是糟糕透了。它提供了一个可编程的网络代理,给予开发者完全控制离线数据的能力有一些重要的事项需要我们注意:

            1.ServiceWorker运行在它们自己的完全独立异步的全局上下文中,也就是说它们有自己的容器。

            2.ServiceWorker没有直接操作DOM的权限,但是可以通过postMessage方法来与Web页面通信。

            3.ServiceWorker没有权限进行LocalStorage,但是可以使用IndexDB。

            4.浏览器可能随时回收ServiceWorker。

            5.ServiceWorker的生命周期是由事件驱动的而不是通过Client。

     下图很好的说明了ServiceWorker的主要生命周期。

          初探ServiceWorker_第1张图片

        第一步注册ServiceWorker。注册ServiceWorker需要一个js文件和指定作用域。我们可以使用chrome://serviceworker-internals来查询浏览器的ServiceWorker的信息。

 
  
//首先根据navigator.serviceWorker来判定浏览器是否支持ServiceWorker
if (navigator.serviceWorker) {
//表明sw.js位于根目录下,同时./表明同一目录下的所有同源请求都可以被sw.js接管。
console.log("ServiceWorkerssupported");sw.js', {scope: './'}.then(function(reg) {
       console.log("ServiceWorkerstered with scope: ", reg.scope);
  }).catch(function(error) {
       console.log("Failedegister ServiceWorker", error);
 });
}

      注册成功后,就会进入安装(Installation)过程。(这里需要说明的是activating阶段是不会触发事件的,只有激活成功后才会触发onactivate事件)。sw.js也就定义了ServiceWorker的表现。

   sw.js:

  var CACHE_NAME = "my_cache";
   var urlsToCache = [
    '/index.html',
    '/css/style.css',
    '/js/script.js'
   ];
//这里的self代表ServiceWorkerGlobalScope
self.addEventListener('install', function(event) {
//这里的waitUtil会在安装成功之前执行一些预装的操作,但是只建议做一些轻量级和非常重要资源的缓存,减少安装失败的概率。安装成功
//后ServiceWorker状态会从installing变为installed 
event.waitUntil(
        caches.open(CACHE_NAME).then(function(cache) {
             console.log('Opendhe : ',cache);
            return cache.addAll(urlsToCache);
      })
    );
});

      安装成功后,会进入激活的流程 (Activation) 。

//在这个流程我们可以做一些诸如释放缓存的操作,激活成功后,ServiceWorker状态会从activating变为activated
self.addEventListener('activate', function(event) {
       event.waitUntil();
});

       到这里ServiceWorker的主流程就已经走完,但是我们要注意ServiceWorker对第一次载入的页面是不起作用的,只有下次访问或者刷新页面后,ServiceWorker才能起作用。注意ServiceWorker的更新,每次访问ServiceWorker控制的页面,浏览器都会去比对当前js文件和注册路径对应的js文件,只要有一个字节不同,浏览器都会获取并安装新文件。但是,这不是立即生效的,原有的ServiceWorker还是会运行,只有当ServiceWorker控制的页面全部关闭后,新的ServiceWorker才会被激活。(Shift+F5)

      ServiceWorker同样有网络代理的功能,它可以截取浏览器请求,由开发者定义返回数据(因为这个权限过大,所以现在只能截取https的Get和Head请求)。

 
  
//通过fetch事件来定义返回数据,但是注意fetch默认是不支持non-cors的,还有一个issue是fetch也不支持30x的重定向请求。 
self.addEventListener('fetch', function(event) {
       event.respondWith(
          new Response("This is my response")
    );
});

     实例Demo  :

       1.首先将Demo工程copy到Tomcat的Webapps目录下,然后启动Tomcat。

       2. 访问http://localhost:8080/serviceworker-offline-demo-master/index.html (ServiceWorker只适用于https请求,但localhost是一个例外)。

         初探ServiceWorker_第2张图片


        第二次刷新后,我们可以查看ServiceWorker的部署情况(chrome://serviceworker-internals)和缓存的文件(crtl+shift+i)。

        初探ServiceWorker_第3张图片

           

           初探ServiceWorker_第4张图片

        3.看下service-worker的代码,激活后的ServiceWorker已经将返回缓存下来。这时候我们关闭Tomcat,再去访问当前页面我们还是会看到和之前一模一样的页面,证明ServiceWorker起了作用。这也正是ServiceWorker提供给我们的核心作用,提供完整的离线数据操作能力,降低应用对网络的依赖,提供富离线体验(对于存储空间的获取Chrome已经提供了其他接口,这里不再赘述)。

    初探ServiceWorker_第5张图片

     

       目前,有7种比较流行的离线操作处理:

           1.fetch only:这种使用fetch和respondWith的方法直接等价于浏览器载入页面,和ServiceWorker一点关系都没有。

           2.cache only:这种方法只匹配Cache中已经存在的request,适用于资源全部缓存后的情况。

           3.cache only with offline.html:这种方法通过在inatsll时预装一定的资源,只缓存预装的资源。

           4.cache then network: 这种方法首先会去匹配缓存中的Request,如果缓存没有命中,则去服务端拿。

           5.network then cache:这种方法首先会去服务端拿,如果获取失败,则会去Cache中匹配。

           6.cache then network and update cache:这种方法首先会去Cache中匹配,同时去fetch,fetch成功后会更新当前Cache。如果Cache匹配到则返回Cache内容,否则返回fetch的内容。

           7.cache then network and update cache  + postmessage:这种方法是6的变种,6的情况有可能造成服务端已经更新但是浏览器还是拿的缓存,所以增加postmessage方法来通知Web页面更新。

           下图是ServiceWorker核心流程:         初探ServiceWorker_第6张图片



你可能感兴趣的:(原创)