乐趣区

关于web:大型-web-应用公共组件架构思考

腾讯文档公共组件历史包袱

1. 架构问题——开发层面

腾讯文档治理的公共组件,设计之初,采纳了各种便于疾速迭代的设计形式,组件代码构造和标准也不足对立,在长期的开发过程中品质没有失去保障。随着需要一直累积,目前存在比拟大的历史包袱。大量组件盘根错节,互相辑合严密,而导致不论如许小的改变都须要数天的恶战能力完,对于开发新性能和修复缺点的同时时,都异样苦楚。次要存在的问题是以下几点。

1.1 难以预料第三方公共组件导致的卡顿

腾讯文档治理的公共组件 (以下称 FC) 次要通过 script-loader 动静加载承载了各个页面的公共业务逻辑,而后将脚本注入到品类的 HTML 中,比方登陆、分享,权限等。这些逻辑都是同一个线程中执行的。

第三方组件是由不同团队和开发人员在保护着,往往有着不可管制的预期,品类方难以保障引入某一个组件的性能是否正当,从而容易导致品类编辑产生卡顿,及性能数据降落。

目前在 excel 中是在调用公共组件的工夫会进行卡顿监控,从而让通过组件不影响详情页的卡顿数据。然而,这无奈从根本上扭转用户主过程卡顿的体验问题。

// 以下伪代码
async loadModule(name){
    // 卡顿监控进行
    jank.stopReport();
    await dosomeThingToLoadModule(name);
    jank.restartReport();}

【案例】关上权限组件 cpu 暴涨,表格卡顿。

1.2 script-loader 加载模式链路十分长,公共组价加载异样提早。

首先须要加载 assets.json 依赖映射文件,而后再异步加载须要性能的 js 代码,最初再初始化组件,向后盾申请组件所需数据,进行渲染,最终能力残缺展现。这是一个十分长的链路,导致用户应用体验相干性能十分耗时。

1.3 公布没有版本控制。

“一次更新,多端降级”原本是 FC 设计之初的一种思考,但在与日俱增的迭代中,咱们积攒了有数 bug,每一次惯例公布之夜都随同着惊恐与噩梦。因为模块 A 公布修复了某个 ppt 的 bug,带了某个 word 的新 bug; 因为某一个版本的降级,带来全品类性能的解体。不足版本控制的结果就是,为了节俭半个小时的包降级工夫,带来了大量调用品类方之间的缺点连锁反应。咱们的设计指标除了尽可能保障公布效率,公布的品质和稳定性也是十分重要的。

1.4 组件调用模式不标准和对立

 // 以下伪代码
 // 业务 A
 const someModule = await loadModule('someModule');
 someModule.init({
    xxx: 'yyyy',
    zzz: 'hello',
    from: 'xxx'
 })
 // 以下伪代码
// 业务 B

 const someModule = await loadModule('someModule');
 someModule.init({
    bbb: 'yyyy',
    ccc: 'hello'
 })

公共组件没有对立的入参标准。每次开发的步骤是,在品类 A 曾经提前接入前提某组件下,品类 B、C 间接复制黏贴过来,而后完事。由此带来的问题是:咱们发现大量因为品类间接差异性导致的公共组件 bug。

1.5 通信机制凌乱

script-loader 即承当了模块加载的职责,外部有又事件通信的逻辑。而公共组件和各个品类的通信除了应用 SLR.listen 外,同时又掺杂 window.addEventListener,导致很多中央反复监听,同时在定位问题时带来了困扰。示例:excel 和 word 对应的通信不一样。

// 伪代码
window.something.listen('someEvent', ()=>{})
// 伪代码
document.addEventlistener.listen('someEvent', ()=>{})

1.6 外部大量应用全局变量

FC 仓库仅 xxx 这个变量就有 500 多处调用方。公共组件应用全局变量容易会造成对详情页的净化,同时让组件逻辑与品类的特定变量耦合,一旦某一个品类对应的字段在迭代中发生变化,就会造成意外 bug。

2. 架构问题——产品层面

架构的不合理设计,会带来一些很大的负面影响,尤其是在需要的开发周期上。这自身是一个恶性循环:

解决方案

综上所述,咱们能够发现,目前咱们原来对第三方专用组件的设计思路是——把专用组件当作编辑页不可或缺的耦合局部。实际上,公共组件,例如,权限,分享,告诉等性能,具备独立利用的性能,它们应该更像是一个可拔插的插件,品类不应该关怀插件的外部细节,插件也不应该有权限影响和毁坏内部主过程。让每次变更都变得可控,并且防止缺点,同时最大水平地满足功能性和灵活性的要求是这次架构设计的指标。

解决方案是建设可拔插式插件化公共组件体系。定制规范的插件化标准,可便于拓展成对第三方开发者开发插件的体系。而 FC 公共组件是作为官网内置插件的模式存在。插件体系有几个比拟要害的点:第一是,第三方插件品质会参差不齐,如何束缚插件的运行不会导致页面的卡顿。第二点是,插件如何调用文档 SDK,也即便如何标准插件和主线程的通信问题。第三点是,插件装置,卸载等后盾治理服务。

2.1 如何平安的运行插件?

2.1.1 插件类型

首先咱们的插件体系分为两类:纯计算逻辑型插件 和 UI 交互式插件。纯计算逻辑插件,比方一个自定义函数,一个自定义工作等。这种插件能够通过应用 web worker 进行多线程计算进行隔离。UI 交互式插件,比方分享弹窗,权限侧边栏等,目前 FC 公共组件全副是这种类型。这种插件须要简单的 UI 交互,咱们能够通过 chrome 的 site-isolation 个性(参考第三方 web 利用过程隔离),用不同域的域名动态创建 iframe,对应的 iframe 内容区域会和主过程进行隔离,从而保障品类的性能和安全性。

2.2 插件如何与主过程通信

出于平安限度,插件不应该间接拜访和写入主过程任何数据。须要建设一套 rpc 通信协议买通插件和主过程的调用。

2.2.1 主过程接口平安裸露

excel 通过 di 依赖服务化后,各种依赖将会以服务化的模式对外提供。对外裸露 api 接口,提供给外部和内部调用。

2.2.2 插件接口平安裸露

基于安全性思考,插件只能调用平台方提供的平安接口,这些接口能够 api 服务化的模式对外裸露。在初始化的过程注入到一个 API 服务工厂中返回给一个缓存对象,提供给插件应用。这些对象如何裸露给插件?这里咱们参考 vscode 机制,能够拦挡 require 接口,将缓存的插件 api 注入到插件上下文。

2.2.3 插件过程 api 和 主过程 api 通信

定义规范的 worker/iframe 过程与主过程通信机制。参照 vscode 咱们能够巧用 proxy 代理(IE 11 不兼容),在插件调用 api 时进行拦挡,对立转换成 message send 调用,能够防止每次 api 调用手动触发 message 通信,简化调用流程。

2.3 插件 UI 扩大点

腾讯文档公共组件交互上只有两种组成,别离是 dialog 弹窗和 slidebar 侧边栏,dialog 弹窗代表是增加文件夹面包、分享面板、vip 领取面板等。侧边栏有权限、告诉列表等。这两种类型组件,咱们别离为插件 UI 展现提供对立的面板。插件编写时须要配置指定类型,调用时在特定区域承载视图。

2.4 插件管理体系

2.4.1 部署

用户开发的插件须要有治理平台,依照标准开发完后,公布到插件治理服务。治理服务具备生成插件形容信息,部署到动态资源,为 UI 组件状态的插件动静生成插件三级域名。

2.4.2 鉴权、装置

用户受权给插件,而后能力实现装置。可拜访权限比方用户根本信息,表格信息,确认许可后,用户信息下绑定应答插件。

2.5 调试

外部插件临时能够间接代理 sheet 本地进行开发。对外部插件须要提供一种规范便捷的调试形式。可选计划有两种,第一种是通过腾讯文档调试工具 Chrome 插件,反对用户装置长期的本地插件,进行开发。

另外一种是用户申请调试开发权限,文档菜单选项内减少插件导入,而后上传到一个长期的调试服务服务,调试好后,再进行公布。

2.6 如何兼容多品类

专用组件插件化依赖品类有雷同的服务化机制。但各个品类因为代码并不对立,插件化如何兼容各个品类呢?

有两种次要办法,第一种是公共组件依照 Excel 服务化进行插件化后行革新,外部再裸露全局变量给其余未革新的品类依照原 FC 调用。

另外一种是将插件化体系进行独自的 SDK 化,SDK 外部做对立的插件化环境及初始化流程,在各个品类再进行引入。

任何架构设计都是历史下的产物,脱离实际状况谈最优解都是不切实际的想法,如何在无限的人力资源和更优的计划中获得均衡是一门学识。一个模式的提出必然面对解决一个问题,随着工夫的推移,需要一直调整和迭代之下,原先的软件设计必定会变得越来越软弱,最终面临天然崩塌,须要重构。但就像一栋房子,工程师设计出构造稳固和思考久远的计划(架构和可扩展性),施工队不偷工减料(代码品质),那么房子也会保值更久,也能更好的面对新工程的一直革新。

——————
文档信息
发表工夫:2020-06-30
笔名:混沌福王
版权申明:如需转载,请邮件知会 imwangfu@gmail.com,并保留此申明
——————

退出移动版