在iOS中,app内嵌网页无非两种方式,一是使用UIWebView(ios 2.0),二是使用WKWebView(ios 8.0);WKWebView修复了很多UIWebView的不足,比如性能、内存等等。
打开一个webview经历的几个阶段:
- 交互无反馈
- 到达新的页面,页面白屏
- 页面基本框架出现,但是没有数据,页面出于loading状态
-
出现所需的数据
如果从程序上观察,WebView启动过程大概分为以下几个阶段:
webview的初始化
与浏览器不同,app中打开webview的第一步并不是建立连接,而是启动浏览器内核。
- 在浏览器中,我们输入地址时,浏览器就可以开始加载页面了;
- 而在客户端中,客户端需要先花费时间初始化WebView完成后,才开始加载。所谓的加载即网络请求;
一般来说HTML在开始接收到返回数据的时候就开始解析HTML并构建DOM树,如果没有JS阻塞的话,一般会相继完成。
WKWebView的内存占用优势比较大,但是初始化比较慢;
UIWebView和android的webView在首次初始化时都要消耗大量内存,之后每次新建 WebView会额外增加一些内存。
在webView中,click事件通常会有大约300ms的延迟。
使用过大图片(2M)可能会导致webView crash。
webView被运营商劫持、注入问题
由于webView加载的页面代码是从服务器动态获取的,这些代码将会很容易被中间环节所窃取或者修改,其中最主要的问题出自地方运行商和一些WiFi。
主要问题包括:
- 无视通信规则强制缓存页面。
- header被篡改。
- 页面被注入广告。
- 页面被重定向。
- 页面被重定向并重新iframe到新页面,框架嵌入广告。
- HTTPS请求被拦截。
- DNS劫持。
针对页面注入,解决方案:
1、使用CSP(Content Security Policy)
CSP可以有效的拦截页面中的非白名单资源,而且兼容性较好。在美团移动版的使用中,能够阻止大部分的页面内容注入。
2、HTTPS
HTTPS可以防止页面被劫持或者注入,然而其副作用也是明显的,网络传输的性能和成功率都会下降,而且HTTPS的页面会要求页面内所有引用的资源也是HTTPS的,对于大型网站其迁移成本并不算低。
HTTPS的一个问题在于:一旦底层想要篡改或者劫持,会导致整个链接失效,页面无法展示。这会带来一个问题:本来页面只是会被注入广告,而且广告会被CSP拦截,而采用了HTTPS后,整个网页由于受到劫持完全无法展示。
对于安全要求不高的静态页面,就需要权衡HTTPS带来的利与弊了。
客户端内部打开第三方webView
一般来说,客户端内的WebView都是可以通过客户端的某个schema打开的,而要打开页面的URL很多都不是写死在客户端内部的,而是可以由url中的参数传递过去的。
那么一旦url可以通过外界自定义,那么就有可能在客户端内部打开一个外部的网页。比如通过扫码等方式。
解决方案:在内嵌的webview中应该限制允许打开的webview的域名,并设置运行访问的白名单。或者当用户打开外部链接钱给用户强烈而明显的提示。
现状与发展
在一个客户端内,native目前主要提供高效而基础的功能;内部的webview则添加一些性能体验要求不高但动态化要求高的能力。
提高客户端的动态性,或者提高webview的性能,都是提升app功能覆盖的方式;目前市面上的各种框架都是对这个趋势的尝试。
随着技术的发展,webview的性能、体验、和安全问题也将逐渐的改善,在App中所占的比重也必将会越来越大。