处理小程序内嵌h5缓存问题
来源:     阅读:825
依创模板店
发布于 2020-11-08 01:33
查看主页

该处理方案非原创,出处是收费的,地址就不贴出来了。

下文是结合公司项目重新整理的,分享一下,独乐了不如众乐乐。

缓存问题

大家都知道,浏览器缓存是个非常有用的特性,它能够提升性能、减少推迟,还可以减少带宽、降低网络负荷。关于浏览器的缓存机制可以总结成下面 2 句话:

更进一步,我们可以粗略理解一下强制缓存和协商缓存的运行机理。若强制缓存(Expires 和 Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified/If-Modified-Since 和 Etag/If-None-Match),协商缓存由服务器决定能否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回 200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回 304,继续使用缓存。这段文字是想让读者拓展一下知识面,假如想要更输入理解,可以通过上面的少量关键字(强缓存、协商缓存、Expire、Cache-Control 等)去查找更详细的资料。

微信的 web-view 组件就是一个嵌在小程序里的浏览器,它在缓存上并没有完全遵照上述的规则,也即它的缓存并不能及时得到清除。想必下面的操作大家都有尝试过:

无法及时刷新缓存会导致发布了最新的页面,而小程序里依然是以前的页面,从而会带来许多问题,如前后台的数据不一致,新的特性无法及时起作用,修改的问题没有得到处理等等。这里需要说明一下:web-view 在过一段时间(时间不定,一天或者者几小时,无显著规律)是可以进行缓存刷新的,而本 Chat 要处理的是及时刷新的问题。

处理问题

处理思路

浏览器访问资源是通过 URL 地址,假如内嵌 H5 的地址不发生变化,那么 web-view 访问资源会从缓存里取,而缓存里并没有最新的数据,这就导致了服务端的最新资源根本无法到达浏览器,这也就解释了为什么修改 Nginx 的 Cache-Control 配置也无法生效的起因。所以,要想彻底处理及时刷新,必需让 web-view 去访问新的地址。我们假定小程序访问的 URL 地址为:

https://www.yourdomain.com/101/#/index

其中 101 就是构建的一个版本号,每次递增,保证次次不同就可。

先来看一遍大概的流程图

处理小程序内嵌h5缓存问题流程图.png

小程序获取最新版本号

//这里加入同步请求到服务器获取最新路径

onShow: function (options) {   this.getFEVersion()},getFEVersion: function () {   //下面是利用Promise进行同步调用的写法   return new Promise(function (resolve, reject) {     wx.request({       //下面是本机调试的一个地址,上线时请改成自己服务端的地址       url: ‘http://192.168.0.168:8090/getFEVersion’,       data: {},       method: ‘POST’,       header: {         ‘content-type’: ‘application/json’,       },       success: function (res) {         if (res.data.success) {           const app = getApp();           //res.data.version 是从服务端返回的最新fe的版本号,即上面的数字101           app.globalData.feUrl = ‘https://www.yourdomain.com/' + res.data.version + ‘/#/index’         }         resolve();       },       fail: function (error) {         console.log(error);         reject();       }     })   }); },
// 接口const H5Rquest = {  // 获取小程序内嵌h5对应的版本号(对应nginx匹配的文件夹路径)  getH5Version() {    return fetch.get(`/api/xxx/${version}/xxx/getH5Version`);  },};// 调用接口componentDidMount() {  H5Rquest.getH5Version()    .then((res) => {    console.log(res);    if (!res || !res.data) {      return WxActions.fnShowToast('无法获取版本号');    }    let params = getCurrentUserParams(this.props.chooseChild);    params = {      ...params,      gitlen: baseH5,      id: this.$router.params.noticeId,      isEdit: this.$router.params.isEdit,    };    const src = `${h5HostName}/${res.data}/#/newsBulletin_announce?${qs.stringify(params)}`;    console.log(src);// 调试模式可以看到跳转的路径能否跟需要的一致    this.setState({src});  })    .catch((err) => {    console.log(err);// 报错信息已经统一阻拦输出  });}// html代码render() {  const {src} = this.state;  return <WebView src={src} />;}

Nginx 配置

Nginx 正则规则,~ 表示区分大小写的正则匹配,\d 是数字的匹配的正则表达式,正好可以匹配 101 这样的数字表达式。

server{      ##其余配置      ##……      ##其余配置      location ~ /\d {         root /mnt/projects/FE/;      }}

在服务器上存放项目的路径为 /mnt/projects/FE/101,下图是 Vue 项目构建好的样子。

000.png

服务端接口

下面是服务端接口的参考代码,我们可以将最新的版本号存入数据库:

@RequestMapping(value = “getFEVersion”, method = RequestMethod.POST)*public* Object *getFEVersion*(HttpServletRequest request) {   ResponseVo responseVo = *new* ResponseVo();   //从数据库中取得最新的版本号   responseVo.setSuccess(“101”);   *return* responseVo;}

总结

到此,我们将小程序发布上线,重启 Nginx 使得配置生效,后续每次构建前台工程,都生成一个新的版本号,如 102、103 等等,将该版本号填入数据库中,后台接口都会及时返回最新版本号,使得小程序总是以最新的路径加载,从而做到 web-view 都能及时的加载最新的 H5 页面。
另外,在链接后面增加时间戳应该也是可以的,具体没验证过,不过哪怕可以,也会造成性能白费的问题,由于相当于每次进入都要重新下载代码,会导致客户体验不好。代码如下

 const src = `${h5HostName}/index.html?stamp=${new Date().getTime()}#/WatchBaby?${qs.stringify(      skipParams,    )}`;    console.log(src);

综上所述,通过接口生成版本号是比较保险的。

注解

[1]:在 app 的 onShow 钩子函数是小程序启动,或者从后端进入前端显示时触发,而且它是所有其余页面 onShow 钩子函数中第一个被执行,因而在这里进行最新版本获取。

[2]:因为需要取得最新版本才能进行其余业务,因而使用同步接口,以此来保证各个生命周期执行的顺序性。

免责声明:本文为用户发表,不代表网站立场,仅供参考,不构成引导等用途。 系统环境 windows
相关推荐
使用Unity和HTML5开发移动游戏的优缺点
nodejs - 爬虫
react引用图片不显示
Docker for Mac启用K8S功能
从网卡发送数据再谈TCP/IP协议—网络传输速度计算-网卡构造
首页
搜索
订单
购物车
我的