前端早早聊大会,前端成长的新起点,与掘金联合举办。
加微信 codingdreamer 进大会专属编辑器/文档技术群。
第十二届|前端可视化专场,7-18 直播,10 位讲师(蚂蚁金服/阿里云等),大会报名地址
本文是第九届 - 在线文档,前端早早聊第 61 场,来自语雀团队高级前端技术专家 - 遇春的分享讲稿简要整理版(完整版含演示请看录播视频和 PPT):
我叫赵勇,花名叫遇春,2009 年加入阿里巴巴淘宝 UED,2015 年加入到蚂蚁体验技术部,目前在语雀团队。
语雀是蚂蚁金服体验技术部的一个创新产品,目前已经在商业化运作。面向个人和组织提供知识创作、组织、交流服务。如果你或者你的团队有知识管理的需要,可以尝试使用语雀。语雀一直很看中创作体验,所以我们在编辑器这个领域一直持续的投入研发,不断迭代,今天要介绍的就是我们自主研发的在线电子表格。
在准备这个分享的时候,我特意去看了下代码的第一次提交记录,是去年的 5 月 29 日,刚好一年的时间,在分享的前面,先给大家介绍下语雀电子表格这一年的研发时间表。
有兴趣的同学可以到语雀的更新日志里了解更多详情。
经过一年的研发,语雀已经能够满足 80~90% 普通 Excel 用户的功能需求,以下是目前我们的功能集,接下来我们会控制新功能的上线节奏,会专门针对已有功能做深度优化,我们希望这些最基础的功能,能够给用户带来喜悦。
通过上述介绍,希望大家能对语雀目前的状态有一个整体的了解。
接下来会分三部分介绍语雀的自研历程:Why、How、What。
在语雀团队以及体验技术部,不管做什么,我们都会多问自己几个为什么,想透为什么做往往比去思考怎么做更重要。
这一部分我会介绍两个问题:
提到电子表格,大家可能最先想到的是 Excel,我们的一些用户在向我们咨询问题的时候也有的说“你们语雀的 Excel 做的怎么怎么样”,我觉得这是 Excel 这么多年来在大家心里形成了根深蒂固的影响,认为表格就是 Excel,但其实 Excel 并不是第一个电子表格软件。第一个电子表格要追溯到 1978 年,美国的一个大牛 Dan Bricklin,在大学实验室做的一款叫做 VisiCalc 的程序。
这是首次利用行列布局来完成数字的录入和计算的软件,虽然简单,但已经具备了如今电子表格最核心的行列模型,当时人们做生意都是用笔记在账本上,一条条记录,到了月底要做汇总对账,效率非常低,而且容易出错,一旦出错就得重头算,所以 VisiCalc 一面世就获得人们的喜爱。这款软件当时就是安装在苹果 2 代的个人电脑上。
就是靠这款软件,当时苹果电脑 2 代打开市场,大卖特卖,乔布斯当年接受采访时说电子表格促进了产业发展,VisiCalc 促成了苹果的成功。
Excel 1.0 面世,这版 Excel 是微软专门为苹果开发的软件,后来盖茨觉得给人写软件不过瘾,就搞出来 Windows。这里面还有一段乔布斯和盖茨的一段恩怨故事。
求伯君在小黑屋里写了 14 个月开发出来的一个国产办公软件 WPS,为国内程序员所敬仰。
微软推出 Office 办公套件,将 Excel 捆绑进来,再后来就是 Excel 一骑绝尘,不断迭代,几乎没有对手。
出现了一个新鲜事物 Google Docs,所有程序员都看呆了,原来在网页上可以实现客户端办公软件的能力,这也一定程度掀起了前端行业的逐步繁荣。
苹果开发了自己的电子表格 Numbers, 这是一款体验很棒的电子表格,不改苹果一贯的简单风格,但藏在里面的有非常强大的功能,目前还不支持在线协同。
微软开始关注在线办公体验,推出在线版的 Office 365, 在线版的 Excel 体验真的很一般。
Airtable 出现,人们开始意识到,原来的电子表格可以这么玩,这就是后面要说到底同构表。
国内才陆续出现在线电子表格的产品,其中 WPS、石墨在这块做的比较早,再后来腾讯和飞书等大厂也开始跟进。
从上述持续 40 几年的历史长河中,电子表格始终保持着旺盛的生命力,功能不断完善,从客户端软件走向线上,足以证明人们对数据处理的需求始终旺盛。
再说回来,为什么语雀要做电子表格,这得从一个词来说起,那就是“知识”,知识怎么定义。
语雀的产品定位是云端知识库,我们内部一直有一个有意思的讨论就是:“什么是知识”,知识和数据之间又有什么关系,直到我们发现这个模型,早在 1888 年,就有人在思考这个问题,托马斯·斯特尔那斯·艾略特在一本《The Rock》书中思考过知识,智慧,咨询之间的关系,后来学者们逐步完善这样一个模型:DIKW 模型。
在这个模型中,可以很清楚的看到,要形成知识,人们首先要从数据处理中产出信息,在这一步表格就发挥了非常重要的作用。文档则是从信息到知识的进一步整理,所以,作为要打造专业的云端知识库,我们在整个知识的产生过程中,自然不能缺失数据处理这一环。
为什么选择自研,我记得小米有品的一个营销负责人有一句话说的很好:“生活中 99% 的产品都值得被重新创造一次”。
作为电子表格这样一款几十年历史的产品,如何重新创造?Airtable 给出了他的答卷,它更像一个在线版的 Database。其实,语雀曾经也在集团内部推出过一版类似 Airtable 的同构表格,是基于 Spreadjs 来做的,发现用户并不是很买账这个新鲜事物,加上后续的一些变故,我们停止继续研发,因为总有一种手脚被束缚的感觉。
2018 年,我们开启了全面自研,先是 kindEditor 的作者隆昊老师的加盟, 语雀的文档编辑器开始全面自研,上线后,性能上有了明显的提升,而且后期的研发和维护效率非常高。用户提的很多问题我们都能第一时间响应,快速解决,这次自研给我们团队带来了很大的信心,我个人也是从文档表格开始进入编辑器领域。
2019 年 5 月我们决定重启表格的研发,抛开 Spreadjs, 全面自研,自研给我们带来的底层的可控性,拓展性,而且从长期看,自研的综合成本效率都很优,选择自研你要慎重的考虑以下几个因素:模型、体验、性能、研发、维护、业务等各种要素。
首先是表格的前端架构图,这是一个非常经典的 MVC 架构,Model 层处理数据,View 层有渲染部分以及工具栏和面板等 UI 部分,渲染部分采用原生的 Canvas 进行绘制,UI 层用了 React,组件库是 antd,图表用了 AntV,UI 层的事件收敛到 Control 层,Handler 去处理事件的参数以及准入规则,然后就交给 Command 去执行数据操作,Command 里会有一个 history 对象去维护一条条命令,包含执行这条命令的参数以及执行中需要携带的快照数据,方便撤销并通过 WebSocket 协同服务将命令同步到其他用户端,架构很简单,在选择技术方案上,语雀一直追求实用与简单。
我想分享的第一个选型是在设计模型时需要考虑的问题,关于产品的选型,也就是前面大家听到的,同构表还是异构表。
可以看出,他们各自有自己的优势和劣势,在数据处理上的实现差异也特别大。
该如何选择,我们最终还是去看用户的需求,会发现两类非常经典的场景,一种是信息结构化,一种是数据处理,这两种场景都非常重要。
数据处理不用多说了,肯定要满足。那信息结构化是什么,就是利用表格天然的行列布局,让信息布局更合理,更容易理解。而信息结构化本身也是前面我们提到的,是知识形成过程中重要的环节,有时候结构化布局也是知识的展现形态的一部分。有些信息必须通过表格才能更好的展现,比如元素周期表,而我们知道同构表是没法做合并单元格的,在信息布局能力上存在较大的缺陷,所以我们最终选择了异构表。
多人实时协同一直是编辑领域最大的难题,表格编辑也同样会遇到,而且会更加复杂,我们先从多人协同的模型说起。
两个人同时基于一条基线开始编辑,当这两条指令 O1、O2 传递到对方那里的时候,要进行变换(OT),这里是最细颗粒的 OP,而通常对于表格操作,比如移动行列,可能会有上千条 OP, 如果刚好另外一个用户也做了类似的批量操作,那么瞬间产生的大量 OP 传递到服务端,服务端需要花费很长时间来做 OP 转换,这就是导致响应延迟,那么用户会进一步产生 OP,造成更多的计算和延迟,形成拥塞。
对于表格的操作,我们可以看这张图。
一个大的数据对象,执行一条 Command,产生数条 Op,如果同步 Op 对性能有太大的挑战,是否可以直接同步Command?我们可以对比看两种模型的差异性。
通过对比两种方案我们最终选择了基于 Command 来做数据同步,每一条 Command 会携带这条命令需要的参数值,传递到其他端,服务端不需要做操作变换,客户端收到 Command 后会直接运行,整个过程非常快,通常一条指令从发出到接收到指令可以在 100ms 以内甚至更快完成,我认为快速将指令同步到各端,是减少冲突的最好办法。
我们知道,通常单元格编辑的指令并不会存在冲突,只有在做行列位置变换或者增减行列时才有可能出现冲突,那么我们需要考虑的问题是:在 100ms 以内同时操作行列的概率有多大,从实际场景来看,这个概率非常小。我们再配合一些冲突后禁止撤销等策略来防止数据的混乱。最终我们采用了一个权衡的方案,同步 Command。从使用效果看,已经能够满足大多数的协同场景。
做电子表格过程中会遇到很多极限边界,比如最大的可计算的数,日期的可识别范围等,接下来我们说说表格最大能支持多少单元格数量。
我们首先看看几个有明确限制的竞品,Google 明确支持 500w 单元格,超过就会报警。飞书是 50w,腾讯文档是 25w。Google 是将数据存储在服务端,运算也在服务端,所以其实理论上可以支持更大的数量,所以看上去只是单元格数量上限的差异,却引来一个很重要的架构选型:数据运算在客户端还是服务端。但其实选择起来也不难,还是要回归业务本身,在线电子表格的大多数场景都不会有那么大的数据量,再基于两个考虑点:
我们选择客户端计算,就是将数据一次性加载到客户端,在用户的浏览器中进行计算,那么这种模式下我们能支持到的最大单元格数量是多少呢?
我们做一个这样的计算,以最小的存储单元格,存储一个十位数的数值,这里只考虑存储值,如果再加上格式,样式,一个单元格大概需要 20~200 个字符,为了做本地的临时存储,我们采用了 localStorage,上限是 5M,(当然,有同学说可以使用 IndexedDB, 还是考虑简单原则,IndexedDB 的异步模型会使整个编程模型变复杂,能不用复杂的方案,我们尽量不用),利用 localStorage,可以支持的单元格数量上限是 25w(10000 行 25 列)。
在这个方案的基础上,我们做了再次压缩优化,最终可以做到 250w 单元格,当然这是在保证离线编辑时体验无损的场景,如果是网络环境好的时候,并且没有大量公式和样式的话,语雀表格可以支持更大量级。
我们看看在百万量级下的数据编辑性能效果。
在表格的操作中,经常会遇到复制粘贴的操作来从其他地方搬运数据过来,比如从网页,或者 Excel、Numbers 将数据迁到线上,复制和粘贴在解决局部或少量数据的时候是最高效的,而通常我们从这些地方复制出来的表格都会遇到一些奇怪的问题,那就是破损。
像上图这样的复制行为,剪切板里的 HTML 就会有奇怪的单元格 Td 或者 Tr 的丢失,对于表格来说,如果解析的时候缺少 Tr、Td,那么单元格的位置就容易解析错误,最终导致粘贴出来的数据错乱,可以看下面的动画。
语雀表格在还原各种复制粘贴中的破损时,表现的更为出色。
除了上述的案例,我们还有很多研发中的小案例,里面包含着我们对产品的思考,对体验的认识,对技术的态度,时间关系不能全部展开。
欢迎大家尝试语雀,并给我们提出宝贵建议。
最后一部分说一下自研中的心得,比较不成体系,不过却是真实感受,希望有自研打算的同学可以有些参考。
招聘时间
”
语雀目前完全自研的编辑器包括以下四款,我们欢迎更多对编辑器感兴趣的同学加入我们。
有兴趣的同学可以直接简历砸过来。
jobs@yuque.com
”
语雀,期待与你一起,提供更佳的创作体验,让知识等于财富。
本文使用 mdnice 排版