老虎证券web端PWA实践总结

1,080 阅读3分钟

    历时两个月,PWA功能终于在web端稳定落地使用,网站 web.itiger.com

    从最新研究到落地上线,遇到不少坑;开发过程中也参考了不少资料,但总有那么几个是没有答案,需要自己摸索结果的。所以,写了这篇总结文章,也阐述一下我在开发过程中遇到的问题,以及解决办法。

    1. 开发环境:vue+webpack,因为项目需要,vue版本v2.5.8,webpack版本v3.8.1

    1. Manifest.json配置

    Manifest.json文件配置的属性是根据manifest的API完成的,其中稍作修改的有两处。改动的原因:webpack打包后的static文件路径(https://static.itiger.com)和真正的访问路径(https://web.itiger.com)是在两个不同的二级域名下,属于跨域,所以对manifest的icon和引入路径稍加配置。


    (from: web.itiger.com )

    1). icon的src属性配置

    因为将Manifest.json文件放在static下,加上webpack的配置原因,icon图片的路劲会稍有不同,为了避免错误和麻烦,直接将图片转成了base64编码,也可以省去向服务器请求icon图片的时间,不占用带宽(如果图片较小,带宽的影响是可以忽略的)。

    2). webpack打包后,manifest.json引入路径

    Manifest.json是在index.html内用link标签引入的,如下所示:

    <link rel="manifest" href="/manifest.json?<%=Date.now() %>">

    (后面的参数:用打包时间做版本号识别)

    但是manifest.json是放在/static文件夹下,经过webpack打包,正常来说也会在/dist/static文件夹下,但考虑上述提到的跨域问题,需要通过webpack(var CopyWebpackPlugin = require('copy-webpack-plugin'))引用依赖进行配置,将manifest.json文件打包到/dist目录下,便于访问。

    plugins: [

    new CopyWebpackPlugin([

    from: resolve('static/manifest.json'),

    to: resolve('dist/manifest.json')

    }

    ])

    ]

    1. Service worker配置

    Service worker 的安装注册,是跟所有教程一样的,不做赘述。可以在这里进行查阅。

    在本项目中,静态缓存借用了workbox-webpack-plugins,service worker.js内有手写部分,所以没有采用workbox 的GenerateSW()方法自动生成,而是用的InjectManifest(),对已有的sw.js文件进行编辑。

    因为workbox是存放在google的cdn上,考虑到客户翻墙问题,就把workbox下载并传到了tiger cdn上,所以,这边涉及到workbox的import问题:

    如果是从google的cdn引入,则webpack配置时importWorkboxFrom : cdn;

    如果是从项目本地引入,则importWorkboxFrom : local;

    如果是从其他地方(如tiger cdn)引入,则importWorkboxFrom : disabled,并且在service worker.js文件内手动配置 importscript( ) 以及 workbox.core.setCacheNameDetails( ) 属性。

    一开始,是考虑将workbox安装包放在项目内,但安装包不小,所以放弃了这种方法改用放在tiger cdn上。但是刚开始的配置是importWorkboxFrom : cdn,所以导致service worker.js文件中出现两个workbox的引入路径,造成引入失败;最终将importWorkboxFrom设置成disabled就解决了。

    1. IndexedDB和Cache Storage缓存清理

    1). Cache storage实时更新数据时清除旧缓存

    Cachestorage 中会有三个缓存,其中预缓存内容存放在***-precache内


    在进行静态资源缓存时,缓存策略总会有选择staleWhileRevalidate()的时候,此时的请求结果缓存在***-runtime内,但会带来一个缓存问题。

    用staleWhileRevalidate( )属性所配置的静态文件,会从cache storage访问,同时从network进行请求获得最新的数据并更新cache的内容


    (from: developers.google.com/web/fundame…)

    Runtime-cache的内容永远保持最新,但是之前的就缓存也没有被删除,会导致本地缓存量一直增加。

    解决办法:每次service worker被激活时('activate',如刷新页面),新得到的请求结果在就缓存被删除后(waitUntil( ))再保存

    this.addEventListener('activate', function(event) {

    var cacheWhitelist = [workbox.core.cacheNames.runtime];

    event.waitUntil(

    caches.keys().then(function(keyList) {

    return Promise.all(keyList.map(function(key) {

    if (cacheWhitelist.indexOf(key) >= 0) {

    return caches.delete(key);

    }

    }))

    })

    )

    })

    2). 清除缓存

    当indexedDB和cache storage全部清空时,service worker.js 执行也不再有意义,所以要将service worker卸载,并重新改下载注册。

    if (window.navigator && navigator.serviceWorker) {

    navigator.serviceWorker.getRegistrations()

    .then(registrations => {

    for (let registration of registrations) {

    registration.unregister()

    }

    })

    }

    卸载之后再清空indexedDB和cache storage

    indexedDB.deleteDatabase('indexedDB的名称')

    caches.keys().then((keyList) => {

    if (!keyList.length) return

    keyList.map((item) => {

    caches.delete(item)

    })

    })

    以上是该项目在落地PWA时遇到的一些坑和大家分享,有什么问题的欢迎指正。