Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Native 性能优化 #26

Open
bigggge opened this issue Oct 30, 2019 · 0 comments
Open

React Native 性能优化 #26

bigggge opened this issue Oct 30, 2019 · 0 comments

Comments

@bigggge
Copy link
Member

bigggge commented Oct 30, 2019

加载性能

首屏预加载

通过原生进行预加载可以极大地提高首屏渲染速度 ,以 Android 为例,通过在闪屏页预先创建 ReactRootView , 并调用 rootView.startReactApplication 方法预渲染 React 组件。同时,这个 rootView 也会被缓存起来,防止不必要的创建。

网络请求预加载

受到 Google Chrome 团队 PWA 解决方案 workbox 库的启发,我们在 React Native 上对 HTTP 请求做了优化,将请求 URL 作为 key,针对 HTTP 请求,提供了以下缓存控制策略:

  • CacheFirst

当匹配到请求之后优先从缓存中取得结果,如果缓存中没有结果,就会发起网络请求,请求成功后将响应更新至 缓存,并返回结果。

  • CacheOnly

直接返回缓存结果。

  • NetworkFirst

优先尝试拿到网络请求的返回结果,如果网络请求成功,就将请求响应写入缓存,如果网络请求失败,那之前被缓存的请求结果将被返回

  • NetworkOnly

仅使用网络请求,请求成功后将响应更新至缓存,并返回响应结果。

  • StaleWhileRevalidate

有缓存的话会直接返回缓存结果,获取缓存的同时会发起网络并更新缓存。

可以看出,StaleWhileRevalidate 策略非常适合书城这类实时性要求一般的场景,不过,在用户进行书城筛选或执行下拉刷新等操作时,会切换到 NetworkOnly 策略来保证用户看到的是最新的内容。以后,我们也会支持最大缓存时间和缓存自动删除等特性来满足更丰富的缓存控制需求。

代码逻辑优化

书城首页加载时需要调用两次 http 请求,代码逻辑大致如下:

const { data } = await ajax.getJSON("/bookcity/country-language");
const { pageData } = await ajax.getJSON("/bookcity/page-list", params);

然而,这段代码会造成隐含的效率问题,这里的 /bookcity/page-list 请求并不依赖 /bookcity/country-language 请求的结果,它们可以并行调用。然而,因为在这里使用了 await 关键词,两个请求调用变成串行的,执行时间几乎是并行时的两倍。我们对该段逻辑做了如下的优化:

const p1 = fetchX("/bookcity/page-list", params, Strategies.StaleWhileRevalidate);
const p2 = fetchX("/bookcity/country-language", null, Strategies.StaleWhileRevalidate);
const { data } = await p1;
const { pageData } = await p2;

在使用 async/await 时,我们仍然需要将流程视为异步的,然后写出同步的代码,或者直接使用 Promise 或者 callback 方式也是不错的选择。

总之,在使用一些新的语法特性时,我们也不能忽视这些新特性可能会对代码产生副作用。

通过以上优化,我们明显降低了用户加载书城的等待时间,根据优化前后的两次测试报告,在首次安装的情况下,加载书城的时间从 12s 优化到 4s,而非首次安装时,从书城加载时间在大部分终端上可以达到 1s 以内。

渲染性能

代码优化

代码层的优化点非常之多,比如常见的 shouldComponentUpdateuseNativeDriver 等优化方式,以下也简单罗列了我们做的一些代码优化点:

  • 代码运行过程中,console 语句会极大地拖累 JavaScript 运行效率,并有内存泄漏的风险。使用 babel-plugin-transform-remove-console 插件自动去除 console 语句。
  • 因为历史代码问题,一直错误地使用 onScroll 方法做曝光上报,导致必须关闭 removeClippedSubviews 才能成功 measure 组件,修复了这个问题后,可以开启 removeClippedSubviews 来提高了列表性能。
  • 启用了腾讯云提供的 图片质量压缩 ,节省了 70% 以上的图片内存占用。
  • 组件的 Render Props 优化
  • 正确使用 React hooks 代替 class 也可以带来一定的 性能提升

使用 V8 内核

在升级 Android 64 位的过程中,Google Play 监控后台收到了大量来自 JSC (JavaScriptCore) 的 crash 报告,根据 github issues , 我们尝试将 React Native 版本升级至 0.59.10,却发现依然没有解决这个 问题 。我们只能选择其他方案,根据一段时间的调研,选择升级 Hermes 引擎或者 V8 引擎应该是可行的解决方案。根据已有的 报告,V8 的内存占用要优于 Hermes,而升级 Hermes 又必须升级 React Native 0.60,成本相对较高,所以我们决定在 Android 平台上优先使用 V8 引擎来替换默认的 JSC。

在使用了 V8 版本应用的过程中,我们发现应用 FPS 有明显提升,通过 Google Play 提供的 公开测试计划,我们推广了包含 V8 引擎的 Webnovel 应用,一段时间后的报告显示,V8 版本的应用 crash 率从 0.81% 下降至 0.63%,但因为测试用户量只有 2000+,我们打算继续在最新版本 (v4.1.0) 上推广 V8 的 beta 包,来采集更精准的用户数据。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant