在协同办公的场景中,Mozilla 开源的together.JS提供了非常丰富的功能基础,稍加修改就能满足我们的很多需求。
上一章说了,TJS很慢,要解决这个问题就得先弄明白慢的原因是什么?
一步步来,先从首页加载开始。
注意:在本章需要websocket协议的相关知识,如有欠缺请自查百度。
3.1 首页加载的速度优化
我们以“tinymce”为例,看看开销大户都有什么,还是老方法,带着问题找答案。
看着有点儿乱,先把这些失败的请求过一遍,把无关紧要的砍掉:
- 干掉google的analytics.js、ga.js ;
- 干掉tabzilla.js ;
关掉这些资源之后,效果很明显。尤其是google那几个,严重影响了加载时间。索性我们把没用的东西都拿掉,就留一个干干净净的编辑框,看看首页的加载能是什么速度?
- 干掉Mozilla的Header和Footer;
- 干掉Bootstrap、parallax和scrollspy等其他js;
- 干掉没有的CSS;
- ……
当我把index.hmlt 精简成上图那样,再来看看首页的加载速度:
秒进,我们的目的达到了。也许首页加载还有优化的可能,但这不再是本文的重点,我们解决下一个问题。
3.2 事件通知延迟的原因
在优化之前,我先介绍一下在“tinymce”这个例子中TJS的实现逻辑。
在together.js的背后,有这么多js的库的支持,它们的作用都是什么呢?
备注:
为了debug方便,要关掉git原始逻辑中的时间戳命名,方法是在together.js中注释掉这一行。
在“tinymce”这个例子中,会用到的库有:
- forms.js :封装了CodeMirror 、ACE 等编辑器的交互接口;
- session.js :业务层核心库,定义消息规则与实现逻辑;
- channels.js :WebSockets 抽象接口,为session.js提供ws协议代理,同时完成json的编解码工作;
它们是如何工作的呢?接下来我用添加一个字符为例,讲述他们的关系和together.js遇到的问题
- forms中的_change()方法是编辑器修改的回调接口,通过该方法能拿到编辑器中的状态和内容;
- session中的session.send方法可以组织数据,调用channels中的_send发送websocket报文;
我们来分析一下,在上述逻辑关系中,得到下面这种现象的原因到底是什么?
输入一个字符,在另外一端得到响应,需要3秒以上的延迟。
- 是forms的回调慢造成的吗?不是!
- 是session组织数据太复杂造成的吗?不是!
- 那直接的原因就是channels在封装websocket时出了问题!
3.3 事件通知延迟的优化
TJS的模块层次还是很清晰的,如果只是websocket封装除了问题,我们只需要修改channels中的逻辑,其他内容不变。
优化两个问题:
- channels都封装了哪些接口,它内部逻辑是什么?
- 什么原因导致了延迟的出现?
TJS还是比较原始的,在_setupConnection方法中,它通过WebSocket()创建ws连接,同时绑定收据收发的方法。
在这里我要声明一下,前阵子解决这个问题的时候,我并没有找到channels内延迟的真正原因!非常遗憾,我的解决方法是用socket.io 重写channels模块,重写_send和_setupConnection等方法。
最终的结果就是,把原来的3秒延迟提高到了几十毫秒,最快也几毫秒就能得到响应!
3.4后记
对于提速这件事,有收获也有遗憾。这些工作是在三周前就做完了。写博客的过程也是一次回顾的过程,对当时的一些想法也有了新的认识。这系列的文档我会一直写下去,预计会有五个章节。
对于together.js ,我的结论是:
- 这是一个非常优秀的开源库,在协同解决方案上能给我们巨大的启迪;
- 这是一个好用的开源库,模块清晰权责明确,二次修改不费劲;
好了,第三章也写完了,下一步要做的就是精简指令,敬请期待下一章内容!