InfoQ我们怎样将官网的加载时间缩短 1.7 秒?


作者丨Kyle Rush
译者丨平川
策划丨万佳
本文最初发布于 Casper 技术博客 , 经原作者授权由 InfoQ 中文站翻译并分享 。
我们在 casper.com 上部署了一个变更 , 从我们自己的服务器而非供应商的服务器上加载一段第三方 JavaScript 代码 。 这个改动将初始渲染时间缩短了 1.7 秒:
InfoQ我们怎样将官网的加载时间缩短 1.7 秒?
本文插图

在桌面 Chrome w/3G 网络下测试的数据上文说的第三方 JavaScript 来自一家名为 Optimizely 的公司 。 通过使用他们的客户端 JavaScript , 我们在 casper.com 上进行 a/b 测试 。 一旦 JavaScript 文件下载完成并执行 , 它将改变网站一半访客的文档 , 从而度量他们对变化的反应 。 为确保尽可能地避免文档样式短暂失效(FOUC) , 我们遵循的最佳实践是以阻塞方式最先加载 Optimizely 。
正如我们所预期 , 采用这种方式加载 JavaScript 代码段会对我们网站的 Web 性能产生负面影响 。
为此 , 我们在很长一段时间进行权衡 。
我们是应该遵循 Web 性能最佳实践并异步加载 Optimizely JavaScript , 还是遵循最佳实践的实验以阻塞方式加载?无论哪种 , 各有利弊 。
我们想到的一个好方法是自托管 Optimizely 代码段 。 一般 , 像 Optimizely 这样的供应商会提供一个 JavaScript 文件的 URL(由他们托管) 。 问题是 , 这会导致新的 DNS 查询以及与供应商服务器之间新的 HTTP 连接和 SSL 握手 。
用这种方式加载的另一项成本是 , 无法使用 HTTP2 多路复用来提供资产 , 而对于浏览器和服务器来说 , 这是一种更有效的通信方式 。 如下面的截图所示 , 从我们一项性能测试中可以看出 , 这会导致 DNS 查询延迟 39ms , 建立服务器连接延迟 54ms , SSL 握手延迟 135ms 。
此外 , 在等待第一个字节时有 175ms 的延迟 , 如果我们能使用 HTTP2 多路复用 , 就可以消除这一延迟 。
InfoQ我们怎样将官网的加载时间缩短 1.7 秒?
本文插图

自托管文件的最后一个好处是 , 我们能更好地控制边缘(CDN)和客户端(浏览器)缓存 。 Optimizely 不会让你控制它们的边缘缓存 , 但它们可以让你控制客户端缓存 。 有一个设置允许你配置 cache-control 值 , 我们将其设置为 2 分钟 。 对我们而言 , 当文件由 Optimizely 托管时 , 这是一个理想设置 。
为了证明自托管更好 , 我们手动复制了 Optimizely JavaScript 文件的内容 , 并在服务器上保存了一个版本 , 同时 , 替换 staging 环境中的引用 , 指向我们的自托管版本 。 结果并不明显 。 这让人相当失望 , 以至于我们的数据分析师说 , 为了在初始渲染时间上节省 200 毫秒 , 不值得做这么多事 。 对这个说法 , 我们一致同意 。
InfoQ我们怎样将官网的加载时间缩短 1.7 秒?
本文插图

我们一直在坚持 , 因为我们认为 staging 环境不是很适合测试这种性能变化 。 我们的 staging 环境缺少很多只在生产环境中运行的第三方 JavaScript 。 所以我们设计了一个产品测试 , 在这个测试中 , 我们部署 Optimizely 的静态自托管版本 , 而数据分析师在 3 天内不对 Optimizely 做任何更改 。
InfoQ我们怎样将官网的加载时间缩短 1.7 秒?
本文插图

下降的时段是在 Optimizely 的自托管版本部署到生产环境期间(测量环境为桌面 Chrome、有线网络连接——当时我们没有在 3G 网络的速度下测量性能 , 这就是为什么文章一开始的图里效果更明显 , 但现在 3G 是我们测量时的标准网速)
从上图可以看到 , 当 Optimizely 代码段的自托管静态版本在生产环境中运行时 , 初始渲染时间出现下降 。 通过自托管 , 由于我们消除了 DNS 查询、Optimizely 服务器连接、SSL 握手、首字节时间 , 并启用了 H2 多路复用 , 所以初始渲染时间大大减少 。


推荐阅读