简介: 鱼乐圈上线啦~

闲鱼会玩社区的重要阵地:会玩圈子今年年初已经上线啦~

作为一款承载着「基于兴趣聚集同好人群」的社区型产品,相较于常规导购型产品来说,在业务复杂度、交互复杂度、性能体验稳定性要求上都要高出许多,像多角色区分嵌套滚动多形态 Feeds 无限加载颜文字等特殊字符处理页面直开视频播控等场景都是导购场景很少遇到的。

本文将围绕着会玩圈子的前端设计、开发过程中遇到的典型问题进行介绍。

关键设计

如上图为会玩圈子的设计大图,可以看到整体的业务逻辑相对较为复杂。并且由于应用中存在多种角色状态,不同角色的用户展示界面和操作逻辑也有差异点存在,前端同学进行开发上手的成本较高。

为了降低前端同学在开发过程中对于全局业务理解的成本,减少沟通中信息传递容易遗漏的问题。我们在设计之初首先进行了最小模块的拆分工作。以模块维度来分配相应的工作,将模块间存在数据共享和数据通信行为进行梳理拆解,以最优方式来分配数据状态维护的最小闭环,降低组件间耦合度。

1. 模块拆分

在此处定义的模块不是前端日常开发中所讲的模块组件拆分,而是能够独立闭环自成体系的一个业务单元。这样在项目过程中除了部分组件间数据传递需要做预先约定外,前端同学仅仅只需要专注于自己所负责的交互场景即可。
  
以圈子模块主页为例,根据设计稿我们将它拆分为了三个独立的业务模块:圈子信息模块、信息流模块和浮层组件模块,他们无论从功能上还是展示上都完全不同。

  • 圈子信息模块: 偏展示型模块。交互较少,根据业务数据展示相应的信息模块内容,需要根据用户当前的身份展示不同类型的模块组件,并且可以根据当前用户的身份来进行权限校验,在未符合时进行友好Tip提示的能力。
  • 信息流模块: 偏交互型模块。需要支持多个列表在Tab下嵌套滚动的能力,模块本身需要维护用户关注状态表、黑名单筛选表和视频播放列表,方便模块中的子组件进行数据共享。并且列表具备单排流和瀑布流两种布局模式,列表内元素存在商品、帖子内容两种类型卡片。支持评论、点赞查看原图、视频播放、触发浮层等多种交互能力。
  • 浮层模块:通用型模块。允许开发者根据业务需求注册相应的模块组件,并且允许配置相应的展示位置、动画效果和图层index

2. 状态值拆分

由于在圈子中有非常多需要共享信息的场景存在,例如用户相关数据、圈子基础信息等,仅仅只是基于业务模块闭环来拆分状态在此处就不适合了。

因此在完成模块拆分之后我们对圈子主页的状态数据进行了梳理,根据组件最小渲染原则来对状态进行相应的拆分,如下图所示:

全局状态

如上图,对于有共享诉求的状态变量,我们优先将这些状态值汇总到一起以方便统一处理。

但由于是C端场景,交互复杂度不高并且考虑到资源包的大小会对用户体验有一定影响。此处的全局状态的管理方案我们选择了直接使用Rax原生的useReducer + useContext来进行处理,并将获取对应实例context 的方法Hooks化以方便开发同学使用,简单demo代码如下所示:

业务组件状态

对于非共享型的数据,则要求放到业务模块中组件渲染影响最小的容器层来进行维护,以单排流的帖子列表为例:

  • 卡片的初始数据通过props形式传入,单一帖子的交互性数据都保留在帖子元素组件一层来维护。
  • 列表容器中除了基础状态信息外,仅仅只做视频播放的控制,不额外触发容器级的重渲染。

实施调优

在多个业务模块进行组合调试的过程中,我们发现交互体验依然有许多不尽人意的问题点:

  • 展示模块过多的情况下,如果在多个Tab下进行数据加载切换过后整个页面的交互会出现明显的卡顿感:比如点击弹出浮层会有明显的等待时延,翻页切换Tab时对应的下标移动会不同步。
  • 浮层容器中注册的部分组件由于依赖共享变量,在共享变量变化时也会触发不必要的重渲染:效果为会跟着闪动一下。
  • 网络状况不稳定的情况,页面展示不够友好的;从用户点击路由跳转到首屏页面展示的等待时间过于明显,与我们要求的页面直开效果相差甚远。

    1. 减少Context.Provider重渲染

    使用Context尽管可以提升状态值传递的便捷性,但是伴随的问题也相当明显:每一次状态值更新变化都会触发整个Context.Provider和下面的子组件重新渲染。

这与我们预期的渲染流程不一致,毕竟我可能只是调整了一个CircleHeader组件所依赖的值,没必要底下CircleSlider组件及其中的列表组件都需要跟着做调整渲染,这个代价是我们无法接受的。

通过在社区中寻找相应的解决方案,我们发现还是有一定技巧来解决这个问题的:Context.Provider其实组件也保持着Rax组件的一致规则:props.children作为传入属性,它如果保持不变就不会触发值diff,进而也就不会出现重渲染的问题了。

那如何才能做到让Provider不会由于props.children的变化产生重渲染呢?通过社区提供的资料,我们发现每次执行的都是JSX转义后的createElement(xxx)。由于每次执行产生的子组件都不一致,所以会导致不必要的重渲染。

为此我们将Context.Provider单独拆分成为一个专门用于传状态值的高阶组件,将子组件以props.children的形式传入:

通过这种方式,我们将CircleApp变为了Stateless Component。只有在首次初始化组件时进行渲染,之后Provider值变化时页不会重新导致GlobalContextProvider执行createElement(CircleApp``)来重新创建组件实例了,减少不必要的js执行。

2. 调整组件结构

如上图可以看到在圈子中存在较多弹出浮层组件的场景,在初版设计过程中考虑到浮层组件由于也需要使用到全局共享变量。因此在设计组件结构之初,将浮层容器组件放到了全局共享变量的GlobalContextProvider组件之内。

但在实际体验过后发现,尽管对于内部的浮层组件获取共享变量较便利了,但反馈出来的问题也相当明显:在使用中低端机型时,如果页面加载的数据过多后会出现明显的延迟感。并且浮层组件仅仅在真实展示的时候才需要用到相应的状态值,非展示时其实不需要关系这些数据的具体内容。

为此我们调整了浮层容器组件和主页常驻组件的层级结构,如上图所示:将常驻组件容器和层容器由原来的嵌套结构优化为了并行结构,两组件之间的数据通信通过方法调用来触发。这样调整之后优点相对比较明显:首先浮层组件可以更加通用、复用性更强。所有所需参数都是通过传参的方式传入,不需要再强依赖全局共享状态,对于开发同学来说维护起来的成本更低。其次因为减少对共享状态值的依赖,子组件不必要的重渲染也都得到了优化。对于中低端机型也能提供相对更好的互动体验。

3. 首屏体验优化 + 容灾机制

在去年下半年的体验优化升级战役中闲鱼的前端页面体验都有了很大的提升:页面首屏等待时间大幅度降低、内容展示更加友好,各个频道页接入渐进式首屏后用户能更快的查看到内容数据。
但在圈子开发的过程中,我们发现对于个性化推荐的场景之前提出的渐进式首屏方案无法较好的支持。为此我们选择了降级方案,调整了从圈子广场页到圈子主页及相关子页面的路由跳转逻辑。

如上图,通过制定上下游页面之间的数据缓存约定来达成容灾和提高交互体验是目的。在每次页面路由跳转时都将相应的业务数据进行缓存,在下一级页面对消费相应的缓存数据。这样不仅可以在网络环境较差的情况下提升用户的体验。同时在接口报错时进行可以起到最低程度的有效兜底,避免用户体感过差。

优化前                                            优化后

在此基础上为了提升页面首屏的渲染速度,我们接入提升数据预取方案离线包缓存方案。将首屏页面渲染过程中最为耗时的资源包加载过程首屏接口请求过程做了并行化处理,从而降低了首屏展示的等待时长。

优化前后效果对比:

优化前 优化后

后续展望

会玩圈子的首个版本在遭遇各种小问题后终于顺利上线了。在这个过程中解决了部分在之前电商导购场景下未经历过的问题:例如角色权限管控,多状态值管理等问题。这些经验的沉淀对于之后闲鱼社区内复杂C端应用体系的成长可以提供一定的助力。

但目前仍有许多的问题点待我们思考优化:

  • 目前圈子主页的首屏平均可交互时长为1000ms左右,用户从点击入口到进入主页内浏览基本无需等待。但我们相信通过根据设备类型来做区分,在进入页面之初降级部分中低端机非必须能力能够为这一类用户提供更快的交互体验。
  • 为了突出社区内不同圈子个性点,相信自定义的装修能力以及定制插件能力在之后是必不可少的。要如何能够基于现有的架构体系快速接入这些业务诉求,也是我们在现有能力上需要预先思考到的
  • 根据业务诉求的变化,如何将从业务模块中产生的组件尽量做到更通用化并且支持多种容器也是需要解决的。

作者:闲鱼技术——庞止

原文链接

本文为阿里云原创内容,未经允许不得转载

0到1:闲鱼高复杂度高性能社区圈子开发实录相关推荐

  1. 他把闲鱼APP长列表流畅度翻了倍(良心教程)

    简介:从"麻绳版顺滑"到"丝般顺滑" 作者:闲鱼技术-云从 1 整体思路 闲鱼在业务的快速迭代过程中,app 的长列表滑动流畅度逐步恶化,对用户浏览内容体验产生 ...

  2. 从0到千万DAU,这5年闲鱼架构如何演进?

    阿里妹导读:闲鱼品牌创立于14年阿里的某个茶水间,从0开始到现在千万DAU,5年时间里闲鱼见证了闲置物品从线下到线上交易的转移.而线上交易的繁荣,则需要业务架构做相应的调整.演进才能支撑业务的快速发展 ...

  3. 阿里要这闲鱼,有何用?

    文丨范东成 社区只是第一步. 8月27日,一则鱼塘关闭整顿的消息出现在了闲鱼. 考虑到鱼塘对闲鱼的重要性,这的确是个十分重要的信号.作为"富人家的穷孩子",闲鱼第一次受到阿里重视, ...

  4. 闲鱼靠什么支撑起万亿的交易规模?| 云原生Talk

    造梦者 | 王树彬,阿里巴巴闲鱼架构负责人 2014年6月28日,阿里即将赴美上市的这一年,西溪园区的一个茶水间里,28个人日夜赶工了三个月后,上线了一个闲置交易平台--闲鱼.今年5月份,在阿里巴巴的 ...

  5. QCon演讲|闲鱼从零到千万DAU的应用架构演进

    导读:业务架构要随着业务发展做相应的演进,继而支撑业务的快速发展.本文主要通过介绍闲鱼从零发展到千万级DAU应用的不同阶段的业务特点.核心问题以及针对性的架构演进,来阐述业务架构的演进思路与心得. 闲 ...

  6. GMTC2019|闲鱼-基于Flutter的架构演进与创新

    2012年应届毕业加入阿里巴巴,主导了闲鱼基于Flutter的新混合架构,同时推进了Flutter在闲鱼各业务线的落地.未来将持续关注终端技术的演变及趋势 Flutter的优势与挑战 Flutter是 ...

  7. 闲鱼的云原生故事:靠什么支撑起万亿的交易规模?

    来源 | 阿里巴巴中间件 作者 | 王树彬,阿里巴巴闲鱼架构负责人 责编 | Carol 2014年6月28日,阿里即将赴美上市的这一年,西溪园区的一个茶水间里,28个人日夜赶工了三个月后,上线了一个 ...

  8. 阿里巴巴闲鱼架构负责人王树彬:万亿交易规模技术架构实践

    中生代技术 链接技术大咖,分享技术干货 全文:5000字 预见未来的最好方式就是创造未来,用「云原生Talk」记录云原生时代下每个造梦者的故事. 造梦者 | 王树彬,阿里巴巴闲鱼架构负责人 2014年 ...

  9. 闲鱼靠什么支撑起万亿的交易规模?

    作者 | 禾易 来源 | 阿里巴巴中间件(ID:Aliware_2018) 造梦者 | 王树彬,阿里巴巴闲鱼架构负责人 2014年6月28日,阿里即将赴美上市的这一年,西溪园区的一个茶水间里,28个人 ...

最新文章

  1. require.js基本认识
  2. 这样用组图创作内容,能让你的文章被转发
  3. 致:测试工程师们!超2000种连接件,下载96页完整选型目录!
  4. 最简单的视音频播放示例7:SDL2播放RGB/YUV
  5. 常用的函数式接口_Consumer接口的默认方法andThen
  6. 读后感:软件测试经验与教训
  7. 2013.8.4thinkPHp学习
  8. spring核心知识点分析
  9. python数值类型和序列类型_Python基础 1数值类型 序列类型
  10. 基于LM317的直流稳压电源设计
  11. 3dmax su 简单_sketchup导入3Dmax技巧
  12. [雨松MOMO程序研究院]Unity3D研究院之构建游戏框架与导出IOS项目(一)
  13. 西门子SITOP电源维修6EP1336-3BA00冗余电源模块维修概述
  14. java 判断日期周几_Java判断当前日期是否在周几到周几时间范围内
  15. NYOJ 小明的调查作业
  16. RHEL6: Server panicked in 'redirfs' module
  17. easyExcel 复杂表头 动态表头
  18. 独家:海尔消金“重仓”医美,月放款量惊人
  19. 淘宝订单转化率低的原因,怎样提高店铺订单转化率,提高店铺订单转化率的小技巧
  20. gradle引入本地jar

热门文章

  1. mysql 货币显示_在MySQL中以正确的格式显示USD货币记录
  2. python适用的操作系统是_操作系统先来先服务python
  3. 1使用技巧_新版PubMed使用技巧1
  4. mongoose 批量修改字段_WordPress图片路径批量替换方法
  5. python十点半游戏代码_Python实现Pig Latin小游戏实例代码
  6. 螺旋桨设计软件_第四届智能工业软件及设计技术研讨会暨2019天洑软件用户大会成功举办...
  7. 来自网页的消息服务器繁处理忙,EventSource 对象用于接收服务器发送事件通知,是网页自动获取来自服务器的更新...
  8. gridview不显示bit_色彩要求高?这款27寸2K +10.7亿色的显示器工作娱乐都适合
  9. cad考试题库绘图题答案_2019年低压电工作业操作证考试最新版题库及答案(一)...
  10. 算法与数据结构c语言版PPT,C语言算法与数据结构.ppt