mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-25 04:17:17 +00:00
docs: 批量博文
This commit is contained in:
122
Chapter2 - Web FrontEnd/2.5.md
Normal file
122
Chapter2 - Web FrontEnd/2.5.md
Normal file
@@ -0,0 +1,122 @@
|
||||
|
||||
# H5性能优化方面的探索
|
||||
|
||||
> H5很重要,很重要,很重要,重要的事情必须重复多遍,H5的优点:跨平台、迭代快、开发体验好。缺点:加载慢,用户体验差。所以在接下来很长一段时间内我将会从H5的几个缺点发面去研究如何优化。
|
||||
|
||||
|
||||
|
||||
## 一、缓存问题及其解决办法
|
||||
|
||||
经常遇到一个问题,H5页面由于缓存问题经常在H5发布新版本之后客户端App看不到最新的效果,之前由于杂七杂八的问题项目工期紧没好好研究,最近抽空研究了下缓存问题。
|
||||
|
||||
缓存问题具体表现为:UIWebview首次打开加载慢;第二次加载速度明显快;H5资源更新过后在App上看不到更改的效果
|
||||
|
||||
为此我认为是缓存造成的问题,我进入App目录下,看到Library下的Caches下面有很多文件名称很长的文件,点击预览可以看到是图片、css等,本来我想着找出H5资源缓存到App中的特点,然后用NSFileManager删除掉缓存文件,发现此路不通。
|
||||
|
||||
#### 我想通过控制变量法研究缓存是否存在。
|
||||
|
||||
#### 做了一个实验。步骤如下:
|
||||
|
||||
* 用HBuilder(一个编辑器,开启后本机端口8020就可以访问网页)打开H5工程
|
||||
* 在App的一个UIWebview页面上通过和电脑在同一个局域网的方式加载网页
|
||||
* 在App上查看效果,观察某个元素的样式
|
||||
* 在HBuilder编辑器中修改元素样式
|
||||
* 在App上将UIWebView返回上一界面,再次进入查看该元素的样式
|
||||
* 确定有没有变化,来确定有没有缓存
|
||||
|
||||
结论:页面实时效果变化的,没有缓存
|
||||
|
||||
对比实验:
|
||||
|
||||
* 用HBuilder(一个编辑器,开启后本机端口8020就可以访问网页)打开H5工程
|
||||
* git提交到服务端
|
||||
* 在App的一个UIWebview页面上通过公网IP的方式加载网页
|
||||
* 在App上查看效果,观察某个元素的样式
|
||||
* 在HBuilder编辑器中修改元素样式
|
||||
* git提交后发布到服务器上
|
||||
* 在App上将UIWebView返回上一界面,再次进入查看该元素的样式
|
||||
* 确定有没有变化,来确定有没有缓存
|
||||
|
||||
结论:页面没有看到最新的效果,明显缓存了。但是我很想知道为什么本地局域网的方式请求网页不会缓存,而通过公网IP的方式会缓存。
|
||||
|
||||
为此,我做了进一步的实验,用谷歌浏览器分别请求本地局域网和公网ip查看资源加载的情况。
|
||||
|
||||
1、公网IP
|
||||

|
||||
|
||||
2、本地局域网
|
||||

|
||||
|
||||
关键词Status Code
|
||||
|
||||
结论:从图上可以看出本地局域网不管首次加载还是刷新都是直接请求;而通过局域网的方式请求:首次请求是从服务器上获取,在此刷新的时候是从(from memory cache)中获取的。
|
||||
|
||||
#### 猜想
|
||||
|
||||
局域网 的方式网速都比较快所以不会缓存;
|
||||
|
||||
公网IP的方式可能由于网速问题会将首次请求到的资源缓存下来。
|
||||
|
||||
所以确定缓存存在了,那么如何避免缓存?
|
||||
|
||||
* App在启动后请求一个接口,这个接口的目的是获取当前H5资源的版本号
|
||||
* 将获得的版本号保存下来(App本地保存)
|
||||
* 由于UIWebView上加载网页,发起网络请求都可以通过一个代理方法所拦截,所以我们可以在这个代理方法中判断url的参数,可能是[http://www.a.com/login、http://www.a.com/login.html、http://www.a.com/login.html?name=geek、http://www.a.com/login\#readme等等,所以我们判断过url后考虑如何将版本号加到url里面](http://www.a.com/login、http://www.a.com/login.html、http://www.a.com/login.html?name=geek、http://www.a.com/login#readme等等,所以我们判断过url后考虑如何将版本号加到url里面)
|
||||
* 由于我们的App使用了不同模块的UIWebView,但是都是在UIWebView上需要大量的JS交互,所以使用了WebViewJavascriptBridge这个库。UIWebView本身的代理方法不会执行,所以修改这个库里面的WebViewJavascriptBridge.m文件的代码,差不多是下面的方式
|
||||
|
||||
```
|
||||
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
|
||||
if (webView != _webView) { return YES; }
|
||||
NSURL *url = [rntity Tag 的资源直接访问equest URL];
|
||||
if ([request.URL.absoluteString containsString:@"http"] || [request.URL.absoluteString containsString:@"https"]) {
|
||||
if ([request.URL.absoluteString containsString:@"?"]) {
|
||||
url = [NSURL URLWithString:[NSString stringWithFormat:@"%@&h5V=%@",request.URL.absoluteString,[ProjectUtil getH5VersionString]]];
|
||||
}else{
|
||||
url = [NSURL URLWithString:[NSString stringWithFormat:@"%@?h5V=%@",request.URL.absoluteString,[ProjectUtil getH5VersionString]]];
|
||||
}
|
||||
}
|
||||
LBPLOG(@"url->%@",[url absoluteString]);
|
||||
__strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate;
|
||||
if ([_base isCorrectProcotocolScheme:url]) {
|
||||
if ([_base isBridgeLoadedURL:url]) {
|
||||
[_base injectJavascriptFile];
|
||||
} else if ([_base isQueueMessageURL:url]) {
|
||||
NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]];
|
||||
[_base flushMessageQueue:messageQueueString];
|
||||
} else {
|
||||
[_base logUnkownMessage:url];
|
||||
}
|
||||
return NO;
|
||||
} else if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
|
||||
return [strongDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
|
||||
} else {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
总结:
|
||||
|
||||
App的缓存问题暂时研究到这里,后期会继续研究其他方面的问题
|
||||
|
||||
# 拓展
|
||||
|
||||
通过浏览器我们知道有的缓存是200 OK(from cache ),有的缓存是304 Not modified。如果运维移除了Entity Tag就一直是200(from cache)。如果没有移除的话2者是交替出现的。
|
||||
|
||||
|
||||
|
||||
为什么2者会有区别?
|
||||
|
||||
* 200 OK(from cache)是直接点击链接或者在浏览器地址栏中输入网址敲回车键的结果
|
||||
* 而304 modified是我们刷新了浏览器页面时触发或者设置了长缓存、但Entity Tags没有移除时触发
|
||||
|
||||
做了 实验得出结论:
|
||||
|
||||
* 直接访问有缓存的网站都触发 200 OK \(from cache\)
|
||||
|
||||
* 刷新浏览器则会触发304
|
||||
|
||||
* 同一域名下,没有 Entity Tag 的资源直接访问,是 200 OK \(from cache\) 的结果
|
||||
|
||||
* 同一域名下,有Entity Tag 的资源直接访问,是出现304 Not Modified
|
||||
Reference in New Issue
Block a user