作者:易芝林(维骏)
语雀桌面端作为语雀为用户提供的生产力工具,上线两年多来一直保持高频的迭代和健康的业务增长。本次主要介绍我们在做桌面端时的一些技术架构思考和实践,同时也将分享我们沉淀的一些通用桌面应用解决方案和经验。
文章会分为四部分,首先会简单介绍语雀桌面端,然后介绍当前语雀桌面端的应用架构以及关键点,之后介绍架构中的几个架构重点项,最后在进行总结。
语雀是孵化自蚂蚁体验技术部的一款笔记与文档知识库工具。我们在两年前,针对语雀用户特点,以及后续发展策略,旨在为创作者提供更好的创作体验,推出语雀桌面客户端。
相较于现有浏览器提供的产品服务而言,我们提供的桌面端产品主要考虑以下几点:
无干扰 :给用户一个沉浸式的创作体验,而不像浏览器有其他窗口、tab 进行干扰,以及用完即走的用户心智。
系统级常驻 :打开速度更快,可以一键启动或者利用各类快捷工具唤起。
集成更多操作系统能力 :提升创作效率的多窗口、系统菜单和快捷键、对文件读写、与系统软件集成等。
离线 :期望能在离线或弱网的情况下,无障碍的进行创作。
研发测主要分为左边三层,最底层是语雀的基础设施,依赖了语雀后台提供或封装的大量云服务,以及底层依赖的安全能力和存储模块。
中间一层是比较偏应用架构的一些能力封装,上面是代码层面用的的辅助能力,还有主进程的模块,然后有给应用提供的一些管理能力和一些跟 UI 相关的功能模块,最上层就是基于底层架构搭建的业务应用。包括桌面端应用比较核心的几个模块,以及一些由子应用方式承接的业务模块(后面也会详细介绍子应用这个概念)
同时最右侧也有很多辅助研发的依赖能力,来完成语雀桌面端的发布、质量和稳定性管理。
相比较普通 web 应用来说,我们觉得桌面端有以下几个能力比较重要:包括安全、软件升级、以及桌面端通用的的基础能力:
安全是一个生产力工具软件的生命线,特别是语雀作为一款知识管理工具,对于安全是非常看重。
客户端软件相比较于 web 来说,还有一个非常大的区别就是有功能更新时,有一个升级过程,不像 web 直接刷新页面即可。语雀桌面端作为迭代迅速的产品,对于升级这块也是踩了不少坑。
语雀桌面端由两大部分组成:包括 Electron 和 Node.js 等基础模块的软件包 + 以及自己的业务代码。
Mac OS:Mac 下的升级流程比较简单,软件下载完成后,利用 hdiutil来模拟用户手动安装流程,用户重启即可完成安装。
Windows:Windows 下因为环境特殊性,需要下载安装包后,通过主进程自动打开安装界面,引导用户进行手动一步一步安装。
其实这种方案很好的满足的我们早期的功能迭代,但是随着用户量上涨,也遇到了很多问题。
比如:
所以我们就调研了一种增量更新的方案,一个 Electron 程序包括 Electron 核心包以及业务代码,其实每次变更的仅仅是业务代码,所以理论上每次更新只需要增量更新业务代码即可。
Mac 下增量直接下载到增量代码后,替换掉即可。
Windows 下比较复杂,我们主要遇到两个问题:
文件占用问题:由于 Windows 系统特性,如果某个文件在使用,会无法删除。所以说如果要替换,肯定关闭程序,然后进行删除操作后再启动。所以我们写了一个 .exe 可执行文件来做关闭程序、更新文件、启动语雀。
UAB 权限控制:文件写入另一个问题是 C 盘文件一般是需要授权才可以操作的。我们软件启动没办法拿到这么高权限。不过还在 Windows 7 及以后新增了一个 PowerShell 功能,通过这个功能执行,能引导用户授权,拿到更高级的权限。
当然过程中还碰到不少细节问题,比如替换过程中路径中英文问题、用户自定义过环境变量位置问题等等
另外我们在做软件的过程中,也沉淀了一些与业务无耦合的组件:
从架构上来说,相较于用了多酷炫的技术,更重要的是研发交付效率高不高,性能怎么样,稳定性高不高。我们认为以下三点是架构好坏评判的重要标准。
从桌面端功能上来说,包括编辑器在内,有超过 60% 的功能模块都是与 web 一致的,所以开始是用到了同构的方案。
同构过程中的一些经验:
虽然同构模式可以解决我们当时遇到的一些问题,但是随着业务规模和功能增加,陆续有些问题暴露出来:
迁移到 Common 目录,各种依赖问题:很多功能在桌面端之前已经上线,有些复杂组件迁移到 Common 下本身也需要耗费不少时间。
缺少动态化能力,迭代滞后(web 与桌面端功能不一致):组件在 web 发布上线后,桌面端需要发布才支持,所以经常会碰到 web 和桌面端不一致的吐槽。
容易出现多端兼容问题(环境依赖等):虽然我们定义了一些规范,但很难彻底避免出现环境依赖问题。
缺少独立沙箱,容易影响主应用(内存泄露、样式) :web 可能用完即走,可以刷新等,不太容易遇到问题,但是桌面端因为是常驻的,如果有些内存泄露或者样式污染问题,就直接影响到整体可用性。
考虑到上述原因,我们将代码复用架构升级成子应用模式,利用桌面端容器,嵌套一个 html 在线或者离线页面。
简单来说,子应用模式可以理解为支付宝九宫格进去的各个小程序模块。
性能是一个桌面端软件必须要面对的问题,是需要持续在不同角度进行优化的
主要包括这几个方面:
性能优化其实不是说做完哪些事情就可以彻底解决,而是一个长期过程。可能我们后续新增功能时,代码里有某一个内存泄露问题,就很容易导致性能拉胯下来。所以我们也建立了一些持续性的机制:
主要包括:
相比较于 web 而言,桌面端的稳定性也是要求更高的。
从研发流程上看,我们主要有两块事情:
注:UIA 是语雀工程师自研的自动化方案,详见 :Macaca MacOS
另外建立了稳定性大盘和实时告警,来感知到线上性能情况。
为了保证每次发布的稳定性,减少回归成本,我们利用每周一次预览版发布的敏捷研发模式,来分解大版本发布带来的集成风险。