【AICon】AI 基础设施、LLM运维、大模型训练与推理,一场会议,全方位涵盖! >>> 了解详情
写点什么

Slack 使用 React 重写 Web 客户端

  • 2017-06-13
  • 本文字数:2996 字

    阅读完需:约 10 分钟

Slack 使用 React 重写了 Web 客户端。在这篇文章中,他们以重写 Emoji 选择器为例,展示了 React 在性能和代码可维护性上给他们带来的巨大好处,以及给用户带来的体验升级。查看英文原文: Rebuilding Slack’s Emoji Picker in React

Slack 正在将 Web 客户端迁移到 React。在最开始,我们的前端使用了 jQuery 和 Handlebars。后来,社区开发出更好的方案用于创建可伸缩的、基于数据驱动的用户界面。jQuery 的“渲染后修改”模式直截了当,但无法与底层的模型保持同步。不同的是,React 的“渲染后再渲染”模式可以保证渲染和模型的一致性。Slack 也紧跟业界的步伐,不断改进前端的性能和可靠性。

我们认为,要引入 React,最好的办法就是先用 React 重写现有产品里的某个特性——这样我们就可以比较出新的开发流程和结果与原先的有什么不同。我们需要重写一个组件,这个组件必须具备交互性,能够自包含,并能够体现 React 在性能方面的优势。我们很快就找到了一个绝佳的组件——被重度使用且极度复杂的 Emoji 选择器。

Virtual DOM 的优势

阅读这篇文章要求对 React 有一定的了解,如果你不熟悉 React,建议先阅读一下 React 的官方文档。简单地说,React 是一个JavaScript 代码库,可以用它方便地开发声明式的、基于数据驱动的用户界面。它的API 很简单,主要由一个组件类组成,这个类包含了一些生命周期方法。组件本身不会生成HTML,相反,它们会生成类似DOM 的树,叫作Virtual DOM。React 会比较两个Virtual DOM,并使用最少的操作将其中的一棵树转换成另一棵树。例如,你可以告诉React 基于新的模型数据重新渲染整个视图,它就会以最快的速度帮你更新文本节点,就好像它有一个精灵军团在帮你完成DOM 的更新操作一样。

React 擅长于将组件在单个模板上的各种行为合并在一起。举个例子,假设一个 Slack 频道变为未读状态时,你通过 JavaScript 来更新频道的边栏:

  • 找出这个频道的 ID
  • 在 DOM 里查找这个频道对应的节点
  • 将节点状态切换成未读(应用 CSS 类)

这个过程很简单,不过你还得为其他事件编写不同的处理逻辑,比如“create”、“join”、“leave”和“rename”。相反,React 把这 5 中情况合并在一起统一处理:

  • 使用新的模型数据重新渲染频道边栏。

我们不需要为每一种 DOM 操作编写代码,而是重新渲染整个组件,React 会为我们完成这个过程。React 通过让代码变得更通用(一刀切的模板)来简化开发。

Emoji 选择器

Emoji 是 Slack UI 的一个组成部分,是最理想的 React 组件。它动态、离散,只需要少量的输入——一组 emoji、默认皮肤和用户的 emoji 使用历史。刚好现有的 Emoji 选择器需要进行性能调优,因为现在不管 emoji 会不会出现在视图里都需要进行渲染。在查找 emoji 时需要切换每个 emoji 的可见性,在重度使用时性能很成问题。新的 Slack 团队准备了 1374 个默认 emoji,这还不包括自定义 emoji(在写这篇文章的时候,Slack 团队总共有 3126 个 emoji,有些团队甚至更多)。重写 Emoji 选择器将会对 Slack 的日常使用产生重大影响。

我们选择在 Storybook 里开发新的组件,Storybook 自称是一个“会让你喜欢上它的 UI 开发环境”。它不要求你改变开发方式,但会让开发、测试和代码审查变得更有趣。你可以在 Storybook 里通过指定不同的属性来定义不同版本的组件。我们为 Emoji 选择器增加了一个新皮肤和几种 emoji 查找方式。

组件布局

React Emoji 选择器的根组件是有状态的,而子组件则是无状态的。我们按照惯例把每个组件导出到单独的文件里。结构如下所示:

Header

  • 分类选项卡:列出了 emoji 的类别,每个类别都有一个“jump to”链接。
  • 搜索框:通过 emoji 的名称或别名过滤 emoji。

Body

  • 固定的头部:显示当前类别选项卡的名称。
  • emoji 列表:所有类别的 emoji 虚拟列表。

Footer

  • emoji 预览:当前选择的 emoji 大图预览。
  • 皮肤选择器:显示当前的皮肤,并可以切换到其他皮肤。
  • 快捷动作(可选的):emoji 的子集,用于快速回复消息。

React 为编写无状态组件提供了两种方式:PureComponent 类和 function。function 更为简单一些,不过它们在每次合并时都会进行渲染,会影响性能。React 团队计划对 function 进行优化,不过目前最好还是避免使用它们。于是我们选择了 PureComponent,它预定以了 shouldComponentUpdate 方法,这个方法可以防止在遇到相同属性时进行更新操作。

React 是一个视图层,把它与自己开发的应用集成要比把它与标准的框架集成直截了当得多。我们不应该破坏 Emoji 选择器的封装性,这样才能很好地与 Slack 现有的模式集成在一起——我们希望这个组件就像是从一个端到端的 React 应用里拿出来的一样。为了保持选择器的纯净,我们在现有的模块系统里创建了一个轻量级的适配器。适配器挂载选择器组件,抽取模型数据,并监听来自外部的信号。采用这种模式,我们可以在开发新功能的同时逐步地迁移代码库。

新的开发流程

虽然使用 React 进行开发是一件很愉悦的事情,但将它集成到我们已有的开发流程里却不是那么一回事——至少在一开始不是那么令人愉快。在那个时候,Slack 使用的是自己开发的前端构建管道,没有所谓的导入、依赖或者复杂的转换(比如 transpilation)。我们决定采用 JSX 语法和 ES2015+,并使用 Babel 和 webpack 在本地构建 Emoji 选择器的资源。

我们预期签入本地编译的代码会很痛苦,但我们低估了接连发生的合并冲突和依赖管理问题是多么令人抓狂。最后,我们尝试将 webpack 集成到我们的开发和 staging 环境里,目标是无缝地替代已有的工作流。为此,我们做了如下的工作。

  • 基于 webpack-dev-server 开发了一个服务,当相关资源和依赖发生变更时,自动编译本地开发服务器上的资源。
  • 支持将 webpack 资源加载到单元测试里(这样就有可能为 React 组件编写测试用例)。
  • 重构生产环境的构建流程,将 webpack 资源推送到我们的 CDN。

通过重写 Emoji 选择器,迫使我们反思我们的构建管道如何能够以一种更健壮、更具伸缩性的方式打包资源。

性能

我们在少量的团队里部署了新的组件,并观察结果。我们观察了 Emoji 选择器在用户使用不同的 5 种交互方式下的渲染速度,对于大部分的操作,React 表现出了显著的速度提升。以下列出了选择器在正常规模团队里的不同渲染时间。

  • 第一次挂载:-270 毫秒(减少了 85%)
  • 第二次挂载:-158 毫秒(减少了 91.3%)
  • 搜索(多个结果):+27 毫秒(增加了 259%)
  • 搜索(一个结果):-25 毫秒(减少了 53.2%)
  • 重置搜索:-68 毫秒(减少了 70.1%)

最大的改进来自“第一次挂载”,从 318 毫秒到 48 毫秒,减少了 270 毫秒,也就是 85%。这要极力归功于 react-virtualized ——一个虚拟列表代码库——减少重新渲染 emoji 的数量。在默认视图上,React Emoji 选择器比 DOM 少渲染了 85%。

或许最让人感到吃惊的变化来自“搜索(多个结果)”,时间从 17 毫秒增加到了 44 毫秒,增加了 27 毫秒。旧选择器只是把不匹配的 emoji 隐藏起来,也就是说,当匹配到大部分 emoji 时会相对较快。但它的缺点也是显而易见的,“搜索(一个结果)”和“重置搜索”就让它的缺点原形毕露,因为此时它需要隐藏更多的 emoji。

未来

使用 React 重写 Emoji 选择器加快了渲染速度,同时简化了代码,让代码更容易维护。我们正在使用 React 重写剩余的代码。我们还有很多工作要做,这次重写将为用户的日常体验带来积极的影响,为此我们感到非常兴奋。与此同时,我们积累了 React 的实践经验,可以帮助平台更进一步。

2017-06-13 19:002800
用户头像

发布了 322 篇内容, 共 134.5 次阅读, 收获喜欢 144 次。

关注

评论

发布
暂无评论
发现更多内容

一文聊透数字化转型,获得企业未来生存的入场券

同道说

产品 架构 数据 趋势 数字化

使用有威胁情报库的SCDN,提供更好的DDOS防护

德迅云安全杨德俊

Flink 中 Slot 机制详解:概念、原理与开发实践

木南曌

flink 实时计算

DR9274-5GK|QCN9224 QCN9274 QCN6274 WiFi7 Lower Power Consumption Network Card

wallyslilly

qcn9274 qcn6274 QCN9224

低代码与数智化OA:重塑企业办公新生态

EquatorCoco

低代码 数智化 OA

2024 年多链代币开发对您的业务有何好处

区块链软件开发推广运营

dapp开发 区块链开发 链游开发 NFT开发 公链开发

Timecho 联合组织 Apache PLC4X 社区 Meetup:探索工业物联网的未来

Apache IoTDB

选择全球直播专线考虑的因素有哪些?

Ogcloud

海外直播专线 海外直播 海外直播网络 全球直播专线 全球直播网络

低代码与系统集成:革新企业应用开发的新动力

不在线第一只蜗牛

低代码 系统集成 项目开发

Mac上非常好用的软件序列号查询工具:KCNScrew for mac激活版

iMac小白

Bartender 5 for Mac:菜单栏图标管理软件

iMac小白

OGNL表达式注入分析 _

EquatorCoco

Java 开发语言

代码审查最佳实践

俞凡

Code Review

温馨提示:不注意这几点,PDT(产品开发团队)就得散!

IPD产品研发管理

产品 IPD 产品研发 研发团队 软件研发

【亚马逊云科技】使用 Vscode Amazon-Q 完成 GUI 界面粉笔脚本开发

亚马逊云科技 (Amazon Web Services)

可视化学习:实现Canvas图片局部放大镜

不在线第一只蜗牛

可视化 canvas 项目开发

苹果Mac电脑最好用的markdown写作软件:Ulysses for Mac最新激活

iMac小白

探索海外应用加速的作用与优势

Ogcloud

网络加速 企业网络 海外网络加速 海外应用加速

Beyond Compare 4 中文版 「Macos文件同步对比工具」

iMac小白

支持M1、IntelliJ IDEA 2023.3.6中文版 附 激活版

iMac小白

一张二维码VS一个行李箱?!看华为云时习知如何助力防城港核电基本安全考试

华为云PaaS服务小智

云计算 数字化转型 华为云

探索Django REST框架构建强大的API

华为云开发者联盟

华为云 华为云开发者联盟 API 开发 web 开发

知识图谱智能问答系统技术实现

悦数图数据库

HN 热帖|替换 Redis 的一场赛跑

小猿姐

数据库 redis 开源协议

海信电视E5N Pro,以新质生产力焕新美好视听体验

脑极体

海信

入围中国大模型 + 知识管理最佳案例 15 强,杭州悦数 x 中国船舶项目收获认可!

悦数图数据库

图数据库

快麦ERP中采购单在旺店通中同步退货

RestCloud

零代码 ERP APPlink 自动化集成

最新体育赛事直播系统源码、示例演示链接及其功能介绍

软件开发-梦幻运营部

Docker技术全景:推动云原生架构的关键力量

快乐非自愿限量之名

Docker 容器 云原生

你知道APP主要关心MobPush消息推送的哪些能力吗?

MobTech袤博科技

ios 开发者 智能推送

SD-WAN网络构建要点简述

Ogcloud

SD-WAN 企业网络 SD-WAN组网 SD-WAN服务商 SDWAN

Slack使用React重写Web客户端_语言 & 开发_Chris Montrois_InfoQ精选文章