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 Web化的一些性能问题 #79

Open
hushicai opened this issue Sep 16, 2019 · 4 comments
Open

React Native Web化的一些性能问题 #79

hushicai opened this issue Sep 16, 2019 · 4 comments

Comments

@hushicai
Copy link
Owner

hushicai commented Sep 16, 2019

本文是基于一个聊天系统项目,主要针对消息列表进行分析。

技术栈:

  • react native 0.48.4
  • react native web
  • redux
  • seamless-immutable
  • reselect

由于是公司项目,这里就不贴源码了。

@hushicai hushicai changed the title React性能优化 React Native Web化的一些性能问题 Sep 16, 2019
@hushicai
Copy link
Owner Author

滚动长列表

优化前

image

滚动消息列表时,FlatList在每次update任务中,所有已渲染的CellRenderer都会被重新update。
这个有点不寻常,按道理已经渲染的Cell不应该update,因为消息数据并没有变化。
检查了一下代码,发现原来ListItem的props上有一个onItemLayout属性,这个属性在每次reconciler的过程中都是变化的,这就会导致PureComponent失效,每次都会进行update。

优化后

避免使用闭包,因为它每次都会生成一个新的函数,改为通过public class fields syntax来声明函数。

image

可以看到,优化后,已渲染过的CellRenderer的颜色条变小了很多,整体的update时间从200多毫秒减少到60多毫秒!

@hushicai
Copy link
Owner Author

发送消息

优化前

image

发送消息时也存在同样的问题,FlatList在update时,所有已渲染的CellRenderer也被重新渲染了。
检查了一下代码,发现原来传了一个index属性,导致在发送消息时,每条消息的index都变了,所以ListItem都会被update。

备注:这里的FlatList是一个inverted FlatList,所以在prepend消息时,index会整体往后移,所以导致整个列表都重绘了。

优化后

去掉index,依赖index的逻辑改为通过message id去查找计算出来。

image

可以看到,优化后,只有最新的一条消息会被重新update,因为它依赖了NextMessage和PrevMessage,而其他的消息就不会被update,整体update时间从200多毫秒减少到50多毫秒!

@hushicai
Copy link
Owner Author

hushicai commented Sep 16, 2019

加载历史消息

优化前

image

消息列表滚到底部后,竟然还有一个将近600毫秒的update任务。
刚开始有点不明觉厉,按道理所有消息都已经加载完了,加载历史消息时,如果没有拉到新消息,应该只会更新ListHeader,为什么会出现这么长的一个update任务呢?

image

检查了一下redux log才发现,原来是加载历史消息的逻辑有点问题。
如果本地现在已经有100条消息,当首次触发加载历史消息时,因为offset丢了,那就会一次性拉100 + 10 = 110条消息,然后query成功后,覆盖掉本地所有消息。
React收到新消息后,就会对整个消息列表进行update。

备注:因为offset没有做本地持久化,所以用户首次进入到聊天窗口,offset丢了。

优化后

这是offset算法设计上的失误,改成按最后一条消息的message id来拉取。

image

可以看到,现在确实只update了ListHeader,更新任务的时间从600毫秒减到6毫秒!

@hushicai
Copy link
Owner Author

hushicai commented Sep 16, 2019

以上性能问题,其实是React常见的bad case,总结一下:

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