HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

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:002888
用户头像

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

关注

评论

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

某能源自保公司:携手嘉为蓝鲸WeOps,共赴运维转型升级之路!

嘉为蓝鲸

数字化转型 可观测 自动化运维

促进云边协同发展,我们一直在努力!

天翼云开发者社区

云计算 算力

企业如何实现运维故障加速闭环的告警体系建设

嘉为蓝鲸

监控告警 告警管理

产品更新 | WeOpsV4.13新增应用归属链路配置,适配用户使用场景

嘉为蓝鲸

weops

MCtalk·CEO对话×酷家乐:从智能涌现到应用涌现,AI在B端做了哪些事?

ToB行业头条

最佳产品奖,TeleDB拿下!

天翼云开发者社区

数据库 云计算

客户在哪儿AI生产的企业全历史行为数据是ToB大客户营销的最佳抓手

客户在哪儿AI

ToB营销 ToB获客 ToB增长 大客户营销

从模糊到清晰:AI 超分引领画质升级

七牛云

视频超分 超分 图像超分

Tele-FLM系列再升级!52B对话模型发布、全球首个万亿单体稠密模型开源

智源研究院

热度继续!从零到一,和亚马逊云科技一起快速启动属于你的大模型

科技热闻

“分离”“聚合”两手抓,天翼云聚合计算赋能多元化应用场景!

天翼云开发者社区

云计算 天翼云

赋能未来教育,3DCAT实时云渲染助力深圳鹏程技师学院打造5G+XR实训室

3DCAT实时渲染

实时云渲染 虚拟仿真云教学 虚拟仿真实训教学

如何搭建设备巡检二维码?看看这篇教程

草料二维码

CMeas度量体系建设:让数据驱动更科学

嘉为蓝鲸

DevOps 研发效能 研发

大揭秘:百度云提供支持的智能审核机制是什么

爱AI的猫猫头

人工智能 网络安全 内容审核 大模型 办公效率

盘点那些国际知名的黑客(下)

网络安全服务

技术 黑客 计算机 黑客攻击 女性

【YashanDB知识库】YashanDB的JDBC/OCI驱动如何设置字符编码

YashanDB

yashandb 崖山数据库 崖山DB

全面解析淘宝商品详情API的SKU信息

技术冰糖葫芦

API Explorer API 编排 api 货币化 API 文档 pinduoduo API

如何挑选最佳多项目进度管理软件?

爱吃小舅的鱼

项目进度 项目进度管理

快手可灵视频生成大模型全方位测评

快手技术

音视频技术 #大模型

“夺金”2024中国互联网大会!天翼云斩获三项大奖!

天翼云开发者社区

云计算 互联网大会

KaiwuDB CTO 魏可伟:差异化创新,面向行业的多模架构

KaiwuDB

多模数据库 KaiwuDB 新版本发布

API签名及加密方式详解

幂简集成

API API签名

面试官:聊聊你对分库分表的理解?

王磊

Java

中国人民大学商学院校友IT互联网+俱乐部会长董哲一行到访亚信科技,共探企业创新之路

亚信AntDB数据库

DataCanvas Alaya九章元识大模型通过北京市生成式人工智能服务备案

九章云极DataCanvas

IT服务管理中的人工智能应用

嘉为蓝鲸

ITSM 大模型 AI Agent 智能服务台

告别手动做PPT!这5款AI一键生成PPT软件,你都知道吗?

彭宏豪95

人工智能 效率工具 PPT AIGC AI生成PPT

亚信安慧AntDB亮相PostgreSQL中国技术大会,获“数据库最佳应用奖”并分享数据库应用实践

亚信AntDB数据库

亚信安慧正式加入多样性算力产业及标准推进委员会

亚信AntDB数据库

华为云Serverless可观测性解决方案打造高效、可靠的云原生应用

华为云PaaS服务小智

Serverless 华为云

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