React Native WebView优化(iOS)

问题

在React Native中打开一个WebView会有非常明显的白屏时间。

 

分析问题

在网上看了一些关于WebView的优化,参考下面这个WebView打开过程:

WebView启动时间

我们可以总结为:

1、节约初始化的时间,预先初始化一个WebView。

2、原生端请求页面资源,优化白屏时间。

3、页面离线化,原生端直接从本地加载网页,优化白屏时间。

 

这三种方案都需要原生端进行改造,而且搞的不好可能出现内存泄漏的风险。页面离线化体验是最好的,但实现最复杂。

根据实际的业务场景,比如我们只想优化几个主页界面WebView的打开速度,笔者尝试把1和2结合起来使用,在用户进入需要打开WebView的页面前,先初始化并加载好一个页面,当用户触发打开WebView时直接把初始化好的页面呈现出来。

想法是美好的,但是能否真的可行呢,先得验证一下,我们从iOS端开始。

 

实验思路

iOS里打开一个webView(现在用的是WKWebView组件,它在iOS 8开始用来替换以前的UIWebView组件)需要三个步骤:

1、实例化一个WKWebView对象。

2、使用这个WKWebView对象加载URL。

3、把这个WKWebView当作子视图加入到父视图中。

 

我们实验组的思路是在父视图加载完毕以后,就执行前两步,在父视图里放一个按钮,用户点击按钮的时候执行第三部。当然还要弄一个对照组,就是用户点击按钮的时候执行1,2,3步,然后我们来对比两个组打开WebView的时间。

 

实验组:

先初始化WebView并加载页面,用户点击以后显示WebView。

代码:

界面:

当我们点击打开百度按钮时,界面会白屏1s左右,然后百度的网页就显示出来了。

 

对照组:

先不初始化WebView,用户点击以后进行初始化,加载和显示WebView。

代码:

和上面实验组当代码相比,我们只是移动了[self initWebView]这行代码的调用位置。

界面和实验组一样。

我们点击打开百度的按钮时,会出现白屏,3s以后才会显示百度页面。

 

实验总结

通过这个实验,我们知道这样做是完全可行的,特别是针对特定页面。比如我们的APP主要页面就是用WebView呈现的。但是我们在React Native里如何做到这一点呢?我们先来看看RN里使用WebView的情况。

 

react-native-wkwebview

https://github.com/CRAlpha/react-native-wkwebview

这个RN组件在RN本身不支持WKWebView时相当有用,但是目前有了https://github.com/react-native-community/react-native-webview以后,这个组件估计是不怎么维护了,不过没有关系,我们来看看这个组件是如何使用WebView的,并尝试给这个组件添加一个上面我们实现的功能,比如提供一个函数可以预先初始化好一个WebView,然后使用组件时通过传递参数指定打开预先初始化好的WebView。

这个组件原生代码的核心文件如下:

CRAWKWebView.m实现了WKWebView,以及里面的各种方法。它提供了一个函数initWithProcessPool来实例化一个真正的WKWebview。

CRAWKWebViewManager.m按照React-Native的规范,实现了一个可以和JS交互的对象。这个对象里,调用initWithProcessPool获得正在的WKWebview。

使用组件时,比如这样写:

<WKWebView style={styles.webView} source={{uri: 'http://www.baidu.com'}} />

实际对应的Native代码如下图,是这个view函数。

也就是说,每次render一个WKWebView组件,就会生成一个新的CRAWKWebView。我们来改造一下,让这个函数返回一个成员变量看看会发生什么。

如下图,我们新加一个pWebView属性,然后在view函数里返回这个_pWebView。

那这个pWebView变量在哪里进行初始化呢?我们可以导出一个函数让JS代码来初始化,如下图,添加一个initWebView函数:

这个函数对_pWebView进行初始化。然后我们就可以在js代码里就进行调用了。

如下图所示,我们一开始就调用WKWebViewManager对webView进行初始化,然后渲染一个WKWebView在界面上。同时界面上会有一个按钮,点击按钮会再次渲染一个新的WKWebView组件。

点击Press me之前

点击Press me按钮以后会这样显示,如下图:

网页一瞬间显示到下面去了,上面的却不见了~。这个现象刚好说明,我们的修改生效了,我们让每个WKWebView组件都返回了是同一个View。但是这个View一下从上面到了下面,还不知道是咋回事。

这样我们就可以针对特定需要打开的WebView进行优化了,具体怎么做呢?上面演示的每次只返回同一个webView明显不满足需求呀。

 

疑惑

1、iOS里一个viewController是如何被其他view进行代理的,生命周期是如何进行的。

2、如果销毁我新建的一个WebView。

 

总结

1、对iOS APP的基本构成有基础认识,比如入口函数,UIWindow对象,它的rootViewController。UIViewController等,学会了单视图开发流程。Object-C的函数声明和调用能看懂了。

2、对iOS APP如何实现多View切换还未了解,各种用到的系统类不熟悉。

3、对RN的允许机制有了更多的了解,RN运行的时候有一个jsruntime在运行JS代码,JS的代码通过UI组件、函数和native代码进行交互,但是只能交互特定的native组件,如果这个组件没有,就需要自己实现。自己实现的过程复杂度并不低于直接写原生。这就给开发者设置了一个障碍,如果你的业务复杂,对性能细节追求卓越,RN不是一个好的选择。如果你的业务能直接使用官方的和社区现有的组件就能实现,那使用RN能节约开发时间,但是如果你的业务会扩展到需要自己开发原生组件,那么就不太适合使用RN了。

4、RN 0.60以后和前面的版本差别比较大,导致升级困难。

4、每一样东西要系统的学都很困难,如何快速搞清楚一个概念需要从多个角度去观察,好的讲解能让人快速理解新的概念。

 

 

参考文章:

https://tech.meituan.com/2017/06/09/webviewperf.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值