Weex在大前端的预加载缓存方案

Weex在大前端的预加载缓存方案

Posted by sunzhongliang on May 20, 2019

Weex在大前端的应用,以及预加载缓存提高页面渲染速度

前言

现在市面上比较流行的混合框架,主要是Facebook的React Native、阿里的Weex(目前已转移到Apache维护)以及Google的flutter;我司在2016年的时候在调研一款混合框架,当时比较了React Native和Weex两款,Weex的Vue语法学习起来几乎没有成本,而React Native的JSX语法上手起来还有一定的学习成本,并且Weex是支持三端通用的,性能上官方介绍是比React Native要好的,于是选定了Weex作为公司的混合项目应用。

正文

Weex的安装

Weex 的安装,首先需要安装NodeJs。在Mac下通过brew install nodejs
然后通过npm install -g weex命令安装weex 。整个环境就安装好了
详细介绍可参考weex官方文档https://weex.apache.org/zh/guide/introduction.html

Weex的使用

Weex是Vue的一个子集,除了一些方法和属性不支持,以及没有js的Dom操作,其他与Vue的语法几乎一致,详情参考平台差异以及在Weex中使用Vue.js会有详细介绍
https://weex.apache.org/zh/guide/use-vue-in-weex.html
有一点需要注意,在使用的时候需要严格按照Weex的文档来,比如属性支持什么单位,以及方法等等,否则会有一些意想不到的坑出现。

Weex的预加载方案

通常在编写完Weex后,编译后会生成js文件,然后把生成的js文件放在服务器通过HTTP的方式加载渲染,或者打包在APP包内,通过本地文件加载的方式渲染
通过打包本地加载的方式渲染不存在性能上的问题,因为没有网络上的消耗,但不能通过热更新的方式更新打包在APP内的js文件
通过HTTP远端加载的方式,因为每次加载js,都会有网络上的消耗,因此今天就说说这个问题我们是怎么解决的。

为什么需要做缓存

  • 减少数据请求,减少设备端网络流量
  • 弱网络状态下,能够快速展示页面
  • 提升我们的综合能力,以及技术水平

APP端缓存的几种形式

  • 设备端初次打开APP时,拉取缓存配置
  • APP端运行时定时拉取缓存配置
  • 当有更新缓存时,发送静默推送,拉取缓存
  • 懒加载形式,按需缓存,在加载页面时通过页面参数进行缓存处理

缓存框架需要满足以下特点

  • 简单,轻量级(对于后端服务器来说不需要太多开发成本)
  • 高可用(缓存加载失败或路径错误,不能报错)
  • 安全性(需考虑一下缓存文件是否存在被别人破坏或替换)
  • 日志记录(需记录缓存读写异常日志,并上传至服务器,便于后期排查问题和追踪命中率)
  • 业务一致性(不能破坏现有代码处理逻辑,如现有url的业务参数)
  • 缓存淘汰(LRU:least recently used最近最少使用),当缓存容量到达一定级别时的处理方案

缓存设计

首先说下第四种懒加载形式按需缓存
因weex sdk加载器通过url(支持远端http url和本地file url)加载,而url又可扩展多个参数,因此适合在url后面追加缓存参数来支持缓存。并且sdk又提供了onJSDownloadedFinish方法,因此实现起来就非常简单了

URL设计
http://172.17.83.27:8081/dist/index.js?cityid=111&_cache=1&_v=2018081123 说明:

  • cityid=111 业务参数,与缓存无关,远端下发
  • _cache=1 有此参数,且值为1,表明启用缓存
  • _v=xxx 版本号(string类型),与本地缓存文件比对若不一致则视为缓存过期,建议采用日期格式,如2018081123

缓存文件设计 当客户端在加载远端地址时http://172.17.83.27:8081/dist/index.js?cityid=111&_cache=1&_v=211,首先判断_cache是否=1,若为1并且有_v版本号就走缓存处理模块,否则就直接加载url进行渲染,然后取http://172.17.83.27:8081/dist/index.js的md5值,判断本地存储中是否包含key,若包含,然后取value中的_v与远端url的_v参数比较,若一致则把value中的文件物理路径参数取出加载, 若不一致,则直接加载远端url渲染,渲染完成后,在weex提供的onjsdownload方法中,进行保存文件操作

设备端初次打开APP时,拉取缓存配置
这种缓存设计,在打开APP时,通过接口拉取缓存配置表

[
    {
        "url":"http://172.17.83.27:8081/dist/index.js?cityid=111&_cache=1&_v=2018081123"
    },
    {
        "url":"http://172.17.83.27:8081/dist/index.js?cityid=111&_cache=1&_v=2018081123"
    }
]

然后循环去比对本地缓存配置是否与url的缓存配置一样,若不一样则在APP后台下载js文件并缓存本地,缓存设计与上面所说到的一致。
也可以通过增量更新js的方式,在拉取配置时,传入本地缓存版本,服务端返回新的缓存版本,客户端在处理完缓存时,把API返回的配置版本cacheVersion覆盖,则下次请求时再传入cacheVersion,然后API判断配置版本一致,则不下发cacheList即可。但这种对缓存的控制要严格,好处是当有n多个cacheList时,不需要下发全部的,只需要下发当前版本变动的cacheList即可

{
    "cacheList":[
        {
            "url":"http://172.17.83.27:8081/dist/index.js?cityid=111&_cache=1&_v=2018081123"
        },
        {
            "url":"http://172.17.83.27:8081/dist/index.js?cityid=111&_cache=1&_v=2018081123"
        }
    ],
    "cacheVersion":1.098
}

APP端运行时定时拉取缓存配置
通常是在运行过程中,通过后台计时器,定时拉取配置列表,若有更新,则随机处理。好处是缓存的及时性比较高。

当有更新缓存时,发送静默推送,拉取缓存 在有缓存更新时,通过发送静默推送的形式,去执行更新逻辑,但需要注意静默推送只有APP在后台时才生效,通常是作为一种辅助手段来处理。

本文首次发布于 孙忠良 Blog, 作者 [@sunzhongliang] , 转载请保留原文链接.