creator-webview加载优化
蝶泳奈何桥. 2024-07-08 15:33:02 阅读 90
title: creator-webview加载优化
categories: Cocos2dx
tags: [cocos2dx, creator, webview, 优化, 加载, 性能]
date: 2024-03-02 13:17:20
comments: false
mathjax: true
toc: true
creator-webview加载优化
前篇
Android WebView shouldInterceptRequest - https://www.jianshu.com/p/7a237e7f055cAndroid WebView的性能问题及缓存机制、资源加载方案 - https://bbs.huaweicloud.com/blogs/219777Android WebView H5 秒开方案总结 - https://juejin.cn/post/7016883220025180191
使用 Android 的 webview 去加载一个 cocos 的 h5 游戏, 如果全部资源都有网络上请求的的话, 即使使用了缓存, 第一次加载还是避免不了加载全部资源的情况, 还是会很慢.
加载H5页面慢的原因
WebView显示H5页面存在一个很明显的性能问题: WebView加载H5页面很慢
加载H5页面慢的原因有:
渲染速度慢:
(1)首先是JS本身的解析过程复杂、解析速度慢;
(2)前端页面又涉及较多的JS代码文件,叠加起来就造成了JS解析效率低;
(3)其次是Android机型碎片化,导致手机硬件设备的性能不可控,有些表现良好,有些表现就较差。页面资源加载慢,每加载一个H5页面都会产生较多网络请求:
(1)HTML的主URL请求;
(2)HTML引用外部的JS、CSS、字体文件、图片文件等都会构造一个独立的HTTP请求。
注:每次加载都会产生这么多的网络请求,会相当耗费流量。
解决方案
可以通过以下三种方案来解决WebView的性能问题:
WebView的缓存机制资源预加载资源拦截
Android WebView 的缓存模式有以下4种:
LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据。LOAD_NO_CACHE: 不使用缓存,只从网络获取数据。LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。LOAD_CACHE_ELSE_NETWORK:只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
思路 01 - 固定文件打包到包内
假设引擎版本不变的情况下, 引擎部分资源是不会变的, 如 cocos-js/cc.xxx.js, 这个也是大头文件, 大小是 2.3m, 所以可以把这个文件打包到包内, 通过拦截 webview 请求判断是否是这个文件, 是的话直接从包内读取这个文件 (实测 100ms 左右), 这可比网络请求快多了.
示例代码
<code>public class WebviewClientHelper extends BridgeWebViewClient {
public WebviewClientHelper(BridgeWebView webView) {
super(webView);
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
WebResourceResponse wrr = super.shouldInterceptRequest(view, request);
LogUtil.D("--- shouldInterceptRequest url: %s", request.getUrl().toString());
String url = request.getUrl().toString();
// 引擎固定的内容
if (url.indexOf("cocos-js") > 0) {
Pattern r = Pattern.compile("cocos-js/cc\\.\\w+\\.js");
Matcher m = r.matcher(url);
if (m.find()) {
String ccjsFile = "cc.e0cbd.js";
byte[] bts = FileTool.getAssetsFileBts(ActivityMgr.getIns().getActivity(), ccjsFile);
return new WebResourceResponse("text/html", "UTF-8", new ByteArrayInputStream(bts));
}
}
return wrr;
}
}
final WebView wv = new WebView(activity);
wv.setWebViewClient(new WebviewClientHelper(wv));
思路 02 - 使用 LOAD_CACHE_ELSE_NETWORK 缓存模式
这种缓存模式 只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
所以进入游戏不需要网络请求, 直接本地 io 缓存文件运行, 速度就会快很多, 但是有个问题就是如果网页更新了怎么办? 结合 cocos 的 MD5 缓存 模式, cocos 打出来的包, 只有 index.html 入口文件不会有文件名变化, 其他所有有变化的文件, 都自动拼上了 md5 的值, 如: index.js 会变成 index.0s3s1.js, 所以只需要对 index.html 进行拦截, 去请求最新网络上的内容即可
示例代码
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
WebResourceResponse wrr = super.shouldInterceptRequest(view, request);
// 入口每次请求最新的
String url = request.getUrl().toString();
if (url.indexOf("index.html") > 0) {
// 因为使用了 LOAD_CACHE_ELSE_NETWORK:只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
// 结合 cocos 的机制, 每次更新只有 index.html 入口文件是不变的, 所以这个文件需要动态请求
HttpHelper.SHttp sh = HttpHelper.okhttpGetSync(MiscFuncApi.packDB.UrlB, null);
if (sh.code == 200) {
LogUtil.D("--- req [%s] success", MiscFuncApi.packDB.UrlB);
return new WebResourceResponse("text/html", "UTF-8", new ByteArrayInputStream(sh.bytes));
}
}
return wrr;
}
cdn 加速
上 cdn 加速, 开启 性能优化
js, html, css 等开启优化
开启 Gzip (推荐) 或者 Brotli 压缩, Gzip 的适配性更好, 普遍都支持
例如 阿里云 cdn
webview 测试是否支持 gzip 或者 brotli
How to enable brotli compression on Android System Webview? - https://stackoverflow.com/questions/65138909/how-to-enable-brotli-compression-on-android-system-webview
可以打开这个网站测试: https://www.cylog.org/headers/, 查看 <code>Accept-Encoding , 查看支持的压缩方式
实际测试, gzip 压缩都支持, br 压缩要求高版本的 chrome 内核才能支持, 所以技术上应该选择支持性更好的方式, 也就是 gzip 压缩方式.
如果 chrome 内核版本, 如 Chrome/122.0.0.0
, >= 120.0.0.0 版本的话, 就是支持 br 的
升级 Android System WebView
直接在 Google Play 上即可, 链接: https://play.google.com/store/apps/details?id=com.google.android.webview
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。