初探PWA

引言

PWA(Progressive web apps, 渐进式Web应用),近两年被炒的十分火爆,它有什么优势呢?css

  • 能够生成桌面小图标,不须要打开浏览器,方便用户访问
  • 经过网络缓存提高页面访问速度,达到渐进式的页面甚至离线访问,提高用户体验
  • 实现相似app的推送功能,生成系统通知推送给用户

上面的这些优势足以让它吸引大量的开发者来探索和应用,毕竟对于web应用来讲,用户体验才是检验web应用的好坏的至高标准,而PWA的这些优势偏偏是开发者在开发时一直追求的html

Service Worker

service worker是实现PWA的核心,service worker是一个独立的浏览器线程,不会对当前程序的执行线程形成阻塞,经过service worker能够实现页面离线访问、用户消息推送等功能vue

生命周期

service worker生命周期彻底独立于网页,所以,要想网页中使用service worker,须要先注册,注册后浏览器会在后台启动相关的安装步骤,通常状况下,咱们须要service worker缓存一些静态文件,所以安装过程当中会对指定的静态文件进行缓存,若缓存成功,则service worker安装成功,若中间有任何一个文件缓存失败,则service worker安装失败,会在下次重启时再次尝试,下面来看一个具体的生命周期图(来源[https://developer.mozilla.org...]()):
webpack

简单应用

看来上面的介绍,是否是跃跃欲试呢?接下来将用代码来简单使用一下service worker,缓存页面中的css、js文件,具体例子:ios

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="/cache1.css">
    <title>pwa</title>
  </head>
  <body>
    <div id="app">test1</div>
    <!-- built files will be auto injected -->
    <script src='/cache1.js'></script>
    <script>
      if ('serviceWorker' in navigator) {
        window.addEventListener('load', function () {
          navigator.serviceWorker.register('/sw.js').then((registration) => {
            console.log('Service Worker Registration')
          }, (err) => {
            console.log(err)
          })
        })
      }
      self.addEventListener('fetch', () => {
        console.log('ss')
      })
    </script>
  </body>
</html>

sw.js:git

var cacheName = 'my-cache'
var cacheList = ['/cache1.css', '/cache1.js']
self.addEventListener('install', function(event) {
  event.waitUntil(
    // 安装成功后向caches中存入须要缓存的文件  
    caches.open(cacheName).then(function (cache) {
        return cache.addAll(cacheList)
    })
  )
});
// 监听service worker fetch
self.addEventListener('fetch', function (event) {
  event.respondWith(
    caches.match(event.request)
        .then(function(response) {
            // 在缓存中查找到匹配的请求,就从缓存返回
            if (response) {
                console.log(response)
                return response;
            }
            // 缓存中没有查找到对应请求,继续网络请求
            return fetch(event.request);
        }
    )
  );
})

如上例所示,利用service worker缓存了页面请求中cache1.js、cache1.css,而后再刷新一下网页,网页请求就会变成下图这样:

在网络请求面版能够很清楚看到这两个文件是从ServiceWorker中请求出来的,可能有些人对caches这个缓存对象还不是很了解,这有一篇文章能够帮助你们理解:传送门github

vue-cli3中的pwa

vue最新脚手架中集成了pwa的插件,将pwa的实现变得更加的简单,只须要在vue.config.js文件中配置pwa属性就能够自动生成对应的service-worker.js配置文件,配置参考:传送门,这里面最核心的就是集成了google团队开发的Workbox,所以关于更加详细的pwa配置能够参考:传送门,这里面包含workbox全部配置项,这里面须要关注的是runtimeCaching属性,这个属性提供五种缓存策略:web

  • CacheFirst:优先取缓存中的数据,若没有则请求网络,请网络也失败就会报错
  • CacheOnly:只从缓存中获取,若没有则报错
  • NetworkFirst:优先从网络获取,若没有则从缓存中获取,缓存获取失败则报错
  • NetworkOnly:只从网络获取,若没有则报错
  • StaleWhileRevalidate:同时从网络与缓存获取,若是缓存可用,取缓存数据,不然从网络中请求,同时缓存会随着网络请求而更新

更加详细的缓存策略能够参考传送门,这里的缓存策略还须要注意的一个问题就是同源策略的问题,通常状况下workbox不会缓存跨域的资源请求,由于在缓存跨域资源时,workbox没法检测跨域请求是否成功,若是失败,用户将没法获取响应数据,可是在NetworkFirst和StaleWhileValidate策略下,能够缓存跨域资源,由于这两个策略的缓存会按期更新,即使出现失败请求,缓存的时间也是短暂的,具体详情能够参考传送门vue-cli

兼容性

ServiceWorker这么牛,是否是就没有什么问题了呢,它最大的问题应该就是它的兼容性问题了,iOS11.3以前都不支持,具体详情参考:传送门,所以vue脚手架在集成时默认在ios下是关闭的跨域

总结

PWA确实是当下很热门的技术,由于它提高了web应用的体验,甚至达到能够和原生app体验相提并论,可是它的问题就是兼容性问题,相信若是兼容性问题获得解决,这种技术必定会被大面积推广到实际应用,但愿经过这篇文章能对你们了解这门技术有必定的帮助。若是有错误或不严谨的地方,欢迎批评指正,若是喜欢,欢迎点赞。

相关文章
相关标签/搜索