H5被某些特殊手机强制缓存导致发布新版本始终无法生效的问题
碰到的问题
- 某些手机上始终打开的都是旧版本H5
- 重启APP + 重启手机都无效
- 卸载APP + 清空APP数据能生效
目的:将H5每次使用的是哪个版本留在历史日志记录里
方便排查问题时, 清晰的知道当时用的H5模块是不是最新的版本
看看是不是真的存在强制缓存的情况
思考方案1
index.html 每次发布新的时候就修改为最新的版本
增加版本号 v0224-1a214b6b324d 发布目录
最终形成以下目录结构:
a.dist
->index.html(可能被强制缓存的情况下如何处理?)
调用location.replace或者azyk.loadUrl
->v0224-1a214b6b324d
->->index.html
->->static
->->js
->v0223-abcdfqeess24d
->->index.html
->->static
->->js
就是需要H5发布的脚本需要改造.
后续要是真碰到强制缓存的情况, 再使用方案2来辅助?
思考方案2
->index.html(可能被强制缓存的情况下如何处理?)
通过数据同步 强制替换目标路径 到 v0224-1a214b6b324d/index.html ?
直接修改H5;菜单配置表的链接即可!这样数据同步后百分百能解决问题
- 增加新推送指令, 让用户下次重新登录, 只刷新菜单表表 即可.
思考方案3
H5的发布 和 APP发布一个流程, 需要上传压缩包到OSS, 然后APP直接按版本号访问OSS?
或者直接下载压缩包, 直接本地访问H5
通过数据同步,可以达到百分百替换H5的效果,避开缓存.
就是需要额外的下载,解压缩 处理逻辑
最终方案4(已上线待验证)
- 将index.html页面进行JS脚本改造
- 假设的极端情况就是index.html也被缓存的情况下
- 使用JS发起HEAD请求自身,将状态记录到缓存里,发现不一样时强制刷新自身
- If-Modified-Since: Mon, 21 Mar 2022 12:40:04 GMT
- If-None-Match: "38b0edc9203dd81:0"
- 强制刷新的方式,不知道以下哪种方式会生效??
- location.reload || location.reload(true)
- azyk.reload()
- location.query += date.now()
- 获取通过XHR直接将index.html GET请求下来(会触发缓存吗?), 然后直接替换 html.outHtml ?
- 假设网络不好HEAD请求耗时几秒, 此时用户正在正常使用H5,此时突然强制刷新,体验会不好,是否可以考虑打个标记,然后在下次进入时发现第一个脚本的.hash码不一直时,再强制刷新? 同时免除本次刷新
- 先看是否有标记,
- 有则强制刷新
- 没有则触发异步刷新,并正常显示
- 主脚本HASH不一致则记录一个标记
- 一致时则无需其它动作
- 先看是否有标记,
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>
<%= htmlWebpackPlugin.options.title %>
</title>
<script>
var eTag = localStorage.getItem('ETag');
if (eTag && eTag.length > 0 && location.search.indexOf(eTag) == -1) {
console.log('添加ETag并重载中')
location.search = 'ETag=' + eTag;
} else {
var r = new XMLHttpRequest();
r.open("HEAD", location.origin + location.pathname + '?t=' + new Date().getTime());
r.onload = function(e) {
var newETag = this.getResponseHeader("ETag");
newETag = encodeURIComponent(newETag.replace(/[^\w]/g, ''));
if (eTag != newETag) {
console.log('ETag已变(下次生效)=' + newETag + '; Old=' + eTag);
localStorage.setItem('ETag', newETag);
} else
console.log('ETag未变')
}
r.send();
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' &&
(CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
document.write('<link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" />')
}
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
相关笔记
- UNI-APP发布后居然只会返回ETag,没有返回Last-Modified,原因未知.
- UNI-APP能正常拿到参数的URL:
- http://localhost:8080/index.html/#/pages/index/index?x=1
location.search=''
onLoad(e) {console.dir(e);}=//x=1
- UNI-APP无法拿到参数的URL:
- location.search='?x=1'
- onLoad(e) {console.dir(e);}=//{}
- http://localhost:8080/index.html/?x=1#/pages/index/index
- http://localhost:8080/index.html/?x=1/#/pages/index/index
- http://localhost:8080/index.html?x=1/#/pages/index/index
- http://localhost:8080/index.html?x=1#/pages/index/index
参考资料
- 解决 Web 缓存的 Python 脚本 - SegmentFault 思否 https://segmentfault.com/a/1190000021262100
- 获取最后修改日期 | MDN https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#%E6%9C%80%E5%90%8E%E4%BF%AE%E6%94%B9%E6%97%A5%E6%9C%9F%E6%94%B9%E5%8F%98%E5%90%8E%E7%9A%84%E6%93%8D%E4%BD%9C
- 绕过缓存 | MDN https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#%E7%BB%95%E8%BF%87%E7%BC%93%E5%AD%98
作者:Asion Tang
凡是没有注明[转载]的文章,本Blog发表的文章版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。