JavaScript 启动性能瓶颈分析与解决方案(2)

另外,统计显示并不是所有的网站都甩给用户一个庞大的 JS 包体,用户下载的经过 Gzip 压缩的平均包体大小是 410KB,这一点与 HTTPArchive 之前发布的 420KB 的数据基本一致。不过最差劲的网站则是直接甩了 10MB 的脚本给用户,简直可怕。

JavaScript 启动性能瓶颈分析与解决方案

通过上面的统计我们可以发现,包体体积固然重要,但是其并非唯一因素,语法解析与编译的耗时也不一定随着包体体积的增长而线性增长。总体而言小的 JavaScript 包体是会加载地更快(忽略浏览器、设备与网络连接的差异),但是同样 200KB 的大小,不同开发者的包体在语法解析、编译上的时间却是天差地别,不可同日而语。

现代 JavaScript 语法解析 & 编译性能评测 Chrome DevTools

打开 Timeline( Performance panel ) > Bottom-Up/Call Tree/Event Log 就会显示出当前网站在语法解析/编译上的时间占比。如果你希望得到更完整的信息,那么可以打开 V8 的 Runtime Call Stats。在 Canary 中,其位于 Timeline 的 Experims > V8 Runtime Call Stats 下。

JavaScript 启动性能瓶颈分析与解决方案

Chrome Tracing

打开 about:tracing 页面,Chrome 提供的底层的追踪工具允许我们使用 disabled-by-default-v8.runtime_stats 来深度了解 V8 的时间消耗情况。V8 也提供了 来介绍如何使用这个功能。

JavaScript 启动性能瓶颈分析与解决方案

WebPageTest

JavaScript 启动性能瓶颈分析与解决方案

WebPageTest 中 Processing Breakdown 页面在我们启用 Chrome > Capture Dev Tools Timeline 时会自动记录 V8 编译、EvaluateScript 以及 FunctionCall 的时间。我们同样可以通过指明 disabled-by-default-v8.runtime_stats 的方式来启用 Runtime Call Stats。

更多使用说明参考我的 gist

User Timing

我们还可以使用 Nolan Lawson 推荐的 来评估语法解析的时间。不过这种方式可能会受 V8 预解析过程的影响,我们可以借鉴 Nolan 在 optimize-js 评测中的方式,在脚本的尾部添加随机字符串来解决这个问题。我基于 Google Analytics 使用相似的方式来评估真实用户与设备访问网站时候的解析时间:

JavaScript 启动性能瓶颈分析与解决方案

DeviceTiming

Etsy 的 DeviceTiming 工具能够模拟某些受限环境来评估页面的语法解析与执行时间。其将本地脚本包裹在了某个仪表工具代码内从而使我们的页面能够模拟从不同的设备中访问。可以阅读 Daniel Espeset 的 Benchmarking JS Parsing and Execution on Mobile Devices 一文来了解更详细的使用方式。

JavaScript 启动性能瓶颈分析与解决方案

我们可以做些什么以降低 JavaScript 的解析时间?

减少 JavaScript 包体体积。我们在上文中也提及,更小的包体往往意味着更少的解析工作量,也就能降低浏览器在解析与编译阶段的时间消耗。

使用代码分割工具来按需传递代码与懒加载剩余模块。这可能是最佳的方式了,类似于 PRPL 这样的模式鼓励基于路由的分组,目前被 Flipkart, Housing.com 与 Twitter 广泛使用。

Script streaming: 过去 V8 鼓励开发者使用 async/defer 来基于 script streaming 实现 10-20% 的性能提升。这个技术会允许 HTML 解析器将相应的脚本加载任务分配给专门的 script streaming 线程,从而避免阻塞文档解析。V8 推荐尽早加载较大的模块,毕竟我们只有一个 streamer 线程。

评估我们依赖的解析消耗。我们应该尽可能地选择具有相同功能但是加载地更快的依赖,譬如使用 Preact 或者 Inferno 来代替 React,二者相较于 React 体积更小具有更少的语法解析与编译时间。Paul Lewis 在最近的 一篇文章 中也讨论了框架启动的代价,与 Sebastian Markbage 的 说法 不谋而合:最好地评测某个框架启动消耗的方式就是先渲染一个界面,然后删除,最后进行重新渲染。第一次渲染的过程会包含了分析与编译,通过对比就能发现该框架的启动消耗。

如果你的 JavaScript 框架支持 AOT(ahead-of-time)编译模式,那么能够有效地减少解析与编译的时间。Angular 应用就受益于这种模式:

JavaScript 启动性能瓶颈分析与解决方案

现代浏览器是如何提高解析与编译速度的?

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/4580ff051f96f509924f038851e9b2be.html