40KB的优化为我们节省了50TB的带宽

2020-10-16 01:51:14

自从Crisp在2015年推出以来,我们将Crisp Chatbox设计为功能齐全,同时又不影响重量。我们反复尝试确保我们的Chatbox脚本(我们的每个用户网站访问者加载的)不会减慢我们的用户网站的速度,并以尽可能快的速度弹出视图。

考虑到性能,我们已经至少减少了对供给库的依赖,并通过使用uglify和cssmin对生产资产进行后处理来最小化所有生产资产。后来,我们甚至将我们的字体文件(Noto Sans)分成了每个字母表的子文件,这将通常加载的字体文件大小从150KB降到了10KB-如果你会说拉丁语,为什么需要加载西里尔文字体字形呢?

我们达到了市场上最轻的Chatbox,压缩大小为232KB(满载),而其他Chatbox提供商通常会加载高达1兆字节(!!)。

通过这篇快速文章,您将了解哪家公司提供最快的网站实时聊天解决方案。

因此,我们接受了这样一个事实,即我们不能对其进行更多的优化。这是本周之前的事了。

就用户体验而言,速度很重要,因为您的聊天小部件加载得越快,与网站访问者或客户互动的机会就越快。

另一方面,加载速度是谷歌和其他搜索引擎众所周知的排名因素。

在我们深入到我们如何优化Chatbox以使其更轻更快的技术解释之前,这里是我们的Chatbox与其他提供商的比较(应用了所有优化)。

这就是为什么我们比较了不同的实时聊天软件,向你展示它们在加载速度方面的表现。

我们分析了以下测量图表:Chatbox字节大小、加载时间、HTTP请求数、解析的DNS主机名和CDN服务器延迟。

我们从欧盟通过光纤互联网和一个良好的WiFi接入点进行了这些比较。我们假设其他提供商在CDN上运行,并在欧盟内有一个存在点,以便将延迟保持在我们测量的最佳水平。使用的测试浏览器是Firefox82,它支持所有最新的优化和Web技术,例如HTTP/3。浏览器缓存在每次测试之前都会被清除。

Chatbox的大小越大,在速度较慢的网络上加载所需的时间就越长。越小越好。

如何衡量:这个co是在打开实时聊天(点击按钮)后,通过欧盟的WiFi热点,通过汇总所有加载的资产从Firefox获得的。我们确保隔离特定于网站的资产,如操作员头像,因为它们的大小在不同网站之间差别很大,因此在此测量中不相关。另外,请注意,这些都是压缩大小,根据Chatbox提供商的不同,可以通过Gzip或Brotli(Brotli比Gzip好,通常高出10%)。

加载Chatbox按钮的时间取决于许多因素,例如Chatbox字节大小、服务器延迟以及Chatbox在准备就绪之前加载的依赖项数量。越低越好。

衡量方式:这一比较是从欧盟WiFi热点上的火狐(Firefox)获得的,方法是将Chatbox按钮首次显示在屏幕上所需的所有资源的所有顺序加载时间相加。在多个资源可以作为阻塞组的一部分并行加载的情况下,采用最大加载时间(为了反映实际)。

会发出多个HTTP请求来加载Chatbox所需的所有资源,加载其用户设置,并建立实时消息传递通道。更多的HTTP请求可能会导致等待网络的时间更长,尽管这种测量对当今使用现代HTTP/2和HTTP/3协议的性能影响较小,这两种协议都将请求流水线传输到相同的重用连接上。(通常)越低越好。

衡量方式:通过计算聊天按钮出现之前发送的所有HTTP请求,以及聊天按钮出现后发送的所有HTTP请求,从欧盟WiFi热点上的Firefox获得了这一比较,这是Chatbox服务(如操作员头像和WebSocket)所必需的。

Chatbox脚本可能需要访问不同子域(主机名)上的资源。主机名越多,DNS解析查询就越多,等待答案所花费的时间也就越多。这还可以防止在单个主机名上高效地流水线传输HTTP请求,因此需要协商不同的安全通道,从而导致将更多的CPU时间花费在硬加密工作上(假设使用HTTPS,这是2020年的标准)。越低越好。

如何衡量:这个比较是通过欧盟WiFi热点上的Firefox获得的,列出了所有不同的解析主机名,以便Chatbox按钮和头像可以出现在屏幕上,并建立了WebSocket连接。

CDN服务器的延迟是影响加载时间的关键。延迟是网络请求流向Chatbox服务器,然后返回第一个应答字节所需时间的基本度量。高延迟,加上大量HTTP请求,将导致极高的加载时间(因为需要多次往返)。越低越好。

测量方法:此比较是从位于法国的一台服务器上的有线光纤连接获得的,该服务器已就其到互联网主干的低而稳定的延迟(通常为5ms)进行了测试,因此反映了一个人在理想条件下可以获得的来自欧盟的实际最小延迟。

重要提示:此比较是在2020年10月写成的。自那以后,这里显示的数据可能发生了变化,因为其他Chatbox提供商可能已经推出了Chatbox的更新,这可能会使其变得更轻或更重。

下面是我们进一步优化Chatbox的动机背后的背景故事:Crisp团队两周前来到了一年一度的远程务虚会。我们降落在一个偏僻的小岛上,来到了一座乡下的大房子里。房子设备齐全,有高速光纤互联网。不幸的是,由于厚厚的墙壁,这座房子的WiFi接收效果很差。糟糕的WiFi意味着更高的数据包丢失率,无论座机连接有多好。

在轻度分组丢失的情况下,TCP带宽会显著降低,因为TCP算法倾向于降低每个丢失分组的带宽窗口,以调整到传输信道的最大限制带宽(这里:WiFi)。这会影响HTTP和一般Web浏览体验(HTTP在TCP上运行)。

更糟糕的是,由于使用UDP的DNS不保证交付,也不重新传输丢失的数据,因此许多DNS查询从未得到响应。DNS失败意味着我们的Web浏览器经常无法解析主机名,最常见的是网站加载的第三方脚本,这些脚本解析了大量的主机名。

据我们所知,Crisp Chatbox也受到了这个糟糕网络的影响。我们可以通过优化Chatbox运行方式中的某些因素来解决这个问题吗?让我想想。

我们的技术团队花了数天时间调查是否有进一步实时聊天优化的机会,并反复在多个级别测试几个想法,并在进行最终实现之前检查对捆绑包大小和速度的任何影响。

通过简化SVG的矢量路径,使用svgo可以将SVG的总大小减少50%,svgo也有一个很好的GUI可用(它们在主CSS中内联为base64);

播放声音时,例如。可以将接收到的消息重新编码为较低的比特率(取决于它们的编解码器,即AAC、MP3或Vorbis),以达到使用高质量耳机的典型人耳不会察觉到太多质量差异的最低限度。对我们来说幸运的是,人的耳朵听力很差,所以我们可以欺骗他们降低音质;

在我们针对所有现代浏览器的现代CSS构建中(它们仍然包含在我们的遗留样式表构建中),可以禁用所有遗留浏览器(2017年前)的免费CSS属性;

Woff字体可以从我们现代的CSS版本中移除,只保留WOFF2(由于特定于字母的Unicode范围规则,这些规则重复了数百次);

一些资源提示";dns-prefetch";和";preconnect";可以被删除,以避免不必要的DNS查询和TCP&;密码握手,当Chatbox关闭时,通常有1%的人看到它的域;

设置主机名#34;settings.crisp.chat";可以合并到子路径上的资产主机名#34;client.crisp.chat";,这将节省1次DNS查询、1次TCP握手和1次密码协商,并允许重复使用已经打开的HTTP/2连接来加载Chatbox设置;

某些CSS规则";可见性:隐藏;";可以调整为";显示:无;";以防止99%的Chatbox用户在屏幕上未显示时加载字体,从而节省20KB的数据和2个HTTP请求;

通过我们的散列后处理器,可以进一步减少CSS类名,它接受人类可读的CSS类名,如";.crisp-client-tainer";,并将它们修改为散列类名,如";.cc-2da1";;

内部的JavaScript属性和函数名可以通过uglify按类进行破坏,这将转换为例如。";this.__LONG_PROPERTY_NAME";到例如。";this.Wr_";(这节省了大量字节);

供应商提供的库应该用特殊的优化来构建,以删除未使用的代码,例如,我们用来建立到服务器的RTM消息传递连接的Socket.IO包含一个遗留的HTTP长轮询连接方法-这是相当繁重的!-尽管我们只需要在今天的现代浏览器中使用WebSocket连接方法;

我们的Content Delivery Network以压缩格式提供所有脚本和样式表,优先使用Brotli压缩算法,并在浏览器不支持Gzip的情况下后退到Gzip。Brotli在减少资源大小方面比Gzip做得更好,并且正在成为当今的标准。

我们在优化工作前后测量了所有核心Chatbox资产(脚本、样式表)的Brotli压缩大小:

那可是一次不错的总减重啊!这并不包括加载的所有其他较小的资源,这些资源加起来总共减少了30%的大小。

此外,我们还希望确保我们的包大小不会因为微小的代码更改而随着时间的推移而变得更大。因此,我们在生产构建结束时实现了一项检查,将生成的构建大小与预先配置的大小基线进行比较。跨过阈值意味着构建会被拒绝,并且不会部署到生产环境中,从而出错并提醒开发人员。

➡️:是的,这是文章封面图片上的协和。当我们想到速度和重量时,它立刻浮现在我们的脑海中。太糟糕了,它不见了!