[译] 2019 前端性能优化年度总结 — 第二部分

让 2019 来得更迅速吧~你正在阅读的是 2019 年前端性能优化年度总结,始于 2016。javascript

[译] 2019 前端性能优化年度总结 — 第一部分
[译] 2019 前端性能优化年度总结 — 第二部分
[译] 2019 前端性能优化年度总结 — 第三部分
[译] 2019 前端性能优化年度总结 — 第四部分
[译] 2019 前端性能优化年度总结 — 第五部分
[译] 2019 前端性能优化年度总结 — 第六部分html

设置切实可行的目标

7. 100 毫秒响应时间,60 fps

为了使用户感受交互流畅,界面的响应时间不得超过 100ms。若是超过了这个时间,那么用户将会认为该应用程序是卡顿的。RAIL,一个以用户为中心的性能模型 为你提供了健康的目标:为了达到 <100 毫秒的响应,页面必须在每 50 毫秒内将控制权交还给主线程。预计输入延迟时间 能够告诉咱们是否到达了这个阈值,理想状况下,它应该小于 50 毫秒。对于像动画这样的(性能)高压点,若是能够,最好不要作任何事情。前端

RAIL

RAIL, 一个以用户为中心的性能模型。vue

此外,每一帧动画应在 16 毫秒内完成,从而达到每秒 60 帧(1 秒 ÷ 60 = 16.6 毫秒)——最好在 10 毫秒如下。因为浏览器须要时间将新帧绘制到屏幕上,所以你的代码应在到达 16.6 毫秒的标记以前执行完成。咱们开始讨论 120 fps(例如 iPad 的新屏幕以 120Hz 运行),而 Surma 已经覆盖了一些 120 fps 的 渲染性能解决方案,但这可能不是咱们目前正关注的目标。java

对性能预期持悲观态度,但要 在界面设计上保持乐观明智地使用空闲时间 。显然,这些目标适用于运行时性能,而不是加载性能。react

8. 速度指数 < 1250,TTI(交互时间) < 5s(3G),关键文件大小 < 170KB(gzip 压缩后)

虽然很难实现,但最好将终级目标定为,首次绘制时间 1 秒之内,速度指数 的值限制在 1250 如下。因为基准是模拟在价值 200 美圆的 Android 手机(如 Moto G4)上,网络为 slow 3G,400ms RTT 和 400kbps 的传输速度,目标是 交互时间低于 5 秒,对于重复访问,目标是低于 2 秒(只能经过 service worker 实现)。android

请注意,当谈到互动指标时,最好区分 First CPU Idle 以及 Time to Interactive ,以免误解。前者是主要内容渲染后的最先点(其中页面至少有 5 秒的响应时间)。后者是页面能够始终响应输入的时间。(感谢 Philip Walton !webpack

咱们有两个主要限制因素,限制咱们制定一个 合理的 目标来保证网络内容的快速传输。一方面,因为 TCP 慢启动,咱们有着网络传输的限制。HTML 的前 14 KB是最关键的有效负载块——而且是第一次往返中惟一能够提供的预算(因为手机唤醒时间,这是在 400ms RTT 状况下 1 秒内得到的)ios

另外一方面,内存和 CPU 有 硬件限制(稍后咱们将详细讨论它们),缘由是 JavaScript 的解析时间。为了实现第一段中所述目标,咱们必须考虑 JavaScript 关键文件大小的预算。关于预算应该是多少有不少不一样的意见(这应该由你的项目的自己决定),可是 gzip 压缩后预算为 170KB 的 JavaScript 已经须要花费 1s 才能在普通手机上进行解析和编译。假设解压缩时 170KB 扩展到 3 倍大小,那么解压缩后(0.7MB)时,那已经多是 Moto G4 或 Nexus 2 上“用户体验的丧钟”。git

固然,你的数据可能显示你的客户没有使用这些设备,可是也许由于低下的性能致使你的服务没法访问,他们根本没有出如今你的分析中。事实上,Google 的 Alex Russels 建议将 gzip 压缩后大小为 130 - 170KB 做为一个合理的上限,当超出这个预算时,你应该进行慎重考虑。在现实世界中,大多数产品都不是很接近(这个标准);当今的 bundle 平均大小约为 400KB,与 2015年底相比增加了 35%。在中等水平的移动设备上,Time-To-Interactive 占 30 - 35 秒。

咱们固然也能够超过 bundle 的大小预算。例如,咱们能够根据浏览器主线程的活动设置性能预算,即在开始渲染以前进行绘制,或 跟踪前端 CPU 热点CalibreSpeedCurve 以及 Bundlesize 等工具可以帮你控制预算,而且能够集成到你的构建过程当中。

此外,性能预算可能不该该是固定值。因为依赖网络链接,性能预算应该(对不一样的网络条件)进行适配,但不管他们如何使用,慢速链接上的负载更加“昂贵”。

From 'Fast By Default: Modern Loading Best Practices' by Addy Osmani

From Fast By Default: Modern loading best practices by Addy Osmani (幻灯片 19)

性能预算应根据普通移动设备的网络条件进行调整。(图片来源:Katie Hempenius) (大图)

定义环境

9. 选择并设置你的构建工具

不要过度关注那些炫酷的东西。 坚持你本身的构建环境,不管是 Grunt,Gulp,Webpack,Parcel 仍是工具组合。只要你得到了所需结果,而且构建过程当中没有任何问题,这就能够了。

在构建工具中,Webpack 彷佛是最成熟的工具,有数百个插件可用于优化构建大小。入门 Webpack 可能会很难。因此若是你想要入门,这里有一些很棒的资源:

10. 默认使用渐进加强

保持 渐进加强 做为前端架构和部署的指导原则是一个安全的选择。首先设计和构建核心体验,而后使用高级特性为支持的浏览器提高体验,建立 弹性 体验。若是你的网站在一台拥有着差劲网络、屏幕以及浏览器的慢速机器上运行的很快,那么它在一台拥有强力网络和浏览器的快速机器上只会运行地更快。

11. 选择一个高性能基准

有不少未知因素影响加载——网络,热量限制,第三方脚本,缓存替换,解析器阻塞模式,磁盘 I/O,IPC延迟,已安装的扩展,杀毒软件和防火墙,后台 CPU 任务,硬件和内存限制,L2/L3 缓存的差别,RTTS等。JavaScript 的成本最高,此外默认状况下阻塞渲染的 web 字体以及图像也常常消耗过多内存。随着性能瓶颈从服务器转移到客户端,做为开发人员,咱们必须更详细地考虑全部这些未知因素。

因为 170KB 的预算已经包含关键路径 HTML/CSS/JavaScript,路由,状态管理,实用程序,框架和应用程序逻辑,咱们必须完全审核咱们选择不一样框架的网络传输成本,解析/编译时间和运行时成本

正如 Seb Markbåge 所指出的,衡量框架启动成本的一个好方法是首先渲染一个视图,而后将其删除后从新渲染,由于它能告诉你框架如何压缩。首次渲染趋向于唤醒一堆懒洋洋的编译代码,一个更大的树能够在压缩时收益。第二次渲染基本上模拟了随着页面复杂性的提高,页面代码是如何重用影响性能特征的。

'Fast By Default: Modern Loading Best Practices' by Addy Osmani

From Fast By Default: Modern Loading Best Practices by Addy Osmani (幻灯片 18, 19).

12. 评估每一个框架以及它们的依赖项

如今,并不是每一个项目都须要框架,并且不是每一个单页应用的页面都须要加载框架。在 Netflix 的案例中,“删除 React,几个库以及对应的客户端代码将 JavaScript 总量减小了 200KB 以上,致使 Netflix 登出主页的交互时间缩短了 50% 以上。”而后,团队利用用户在目标网页上花费的时间为用户可能使用的后续网页预读取 React(详情请继续阅读)。

这听起来很明显可是值得一提:一些项目也能够从彻底删除现有框架中收益。一旦选择了一个框架,你将至少使用它好几年,因此若是你须要使用它,请确保你的选择获得了充分的考虑

Inian Parameshwaran 测量了排名前 50 的框架的性能足迹(针对首次内容渲染——从导航到浏览器从 DOM 渲染第一部份内容的时间)。Inian 发现,单独来讲,Vue 和 Preact 是最快的——不管是桌面端仍是移动端,其次是 React(幻灯片)。你能够检查你的候选框架和它建议的体系结构,并研究大多数解决方案如何执行,例如平均而言,使用服务端渲染或者客户端渲染。

基线性能成本很重要。根据 Ankur Sethi 的一项研究,“不管你对它的优化程度如何,你的 React 应用程序在印度的普通手机上的加载时间绝对不会低于 1.1 秒。你的 Angular 应用程序始终须要至少 2.7 秒才能启动。你的 Vue 应用程序的用户须要等待至少 1 秒才能开始使用它。”不管如何,你可能不会讲印度定位为主要市场,可是网络不佳的用户在访问你的网站是会得到相似的体验。做为交换,你的团队固然能够得到可维护性和开发人员效率。但这种考虑值得商榷。

你能够经过探索功能,可访问性,稳定性,性能,包生态系统,社区,学习曲线,文档,工具,跟踪记录,团队来评估 Sacha Greif 的12 点量表评分系统 中的框架(或者任何其余 JavaScript 库)。可是在艰难的时间表上,在选择一个选项以前,最好至少考虑大小 + 初始解析时间的总成本;轻量级选项,如 PreactInfernoVueSvelte 或者 Polymer,均可以很好地完成工做。基线的大小将定义应用程序代码的约束。

一个很好的起点是为你的应用程序选择一个好的默认堆栈。Gatsby.js(React), Preact CLI,以及 PWA Starter Kit 为中等移动硬件上的快速加载提供了合理的默认值。

JavaScript processing times in 2018 by Addy Osmani

(图片来源: Addy Osmani)(大图)

13. 考虑使用 PRPL 模式以及应用程序 shell 架构

不一样的框架会对性能产生不一样的影响,而且不须要不一样的优化策略,所以你必须清楚地了解你将依赖的框架的全部细节。构建 Web 应用程序时,请查看 PRPL模式应用程序 shell 体系结构。这个想法很是简单:推送初始路由交互所需的最少代码,以便快速渲染,而后使用 service worker 进行缓存和预缓存资源,而后异步地延迟加载所需的路由。

PRPL Pattern in the application shell architecture

PRPL 表明按需推送关键资源,渲染初始路由,预缓存与按需求延迟加载剩余路由。

Application shell architecture

应用程序 shell 是驱动用户界面所须要的最少 HTML,CSS 和 JavaScript。

14. 你是否优化了各个 API 的性能?

API 是应用程序经过所谓的端点向内部和第三方应用程序公开数据的通讯通道。在 设计和构建 API 时,咱们须要一个合理的协议来启动服务器和第三方请求之间的通讯。Representational State Transfer (REST) 是一个合理的成熟选择:它定义了开发人员遵循的一组约束,以便以高性能,可靠和可扩展的方式访问内容。符合 REST 约束的 Web 服务称为 RESTful Web 服务

HTTP 请求成功时,当从 API 检索数据,服务器响应中的任何延迟都将传播给最终用户,从而延迟渲染。当资源想要从 API 检索某些数据时,它将须要从相应的端点请求数据。从多个资源渲染数据的组件(例如,在每一个评论中包含评论和做者照片的文章)可能须要屡次往返服务器以在渲染以前获取全部数据。此外,经过 REST 返回的数据量一般大于渲染该组件所需的数据量。

若是许多资源须要来自 API 的数据,API 可能会成为性能瓶颈。GraphQL 为这些问题提供了高性能的解决方案。自己,GraphQL 是 API 的查询语句,是一个使用你为数据定义的类型系统执行查询的服务端运行时。与 REST 不一样,GraphQL 能够在单个请求中检索全部数据,而且响应将彻底符合要求,而不会像 REST 那样过多过少读取数据。

此外,因为 GraphQL 使用 schema(描述数据结构的元数据),它已经能够将数据组织到首选结构中,所以,例如,使用 GraphQL,咱们能够删除用于处理状态管理的 JavaScript 代码,生成更简洁的应用程序代码,能够在客户端上运行得更快。

若是你想开始使用 GraphQL,Eric Bear 在 Smashing 杂志上发表了两篇精彩的文章:A GraphQL Primer: Why We Need A New Kind Of API 以及 A GraphQL Primer: The Evolution Of API Design (感谢提示,Leonardo)。

Hacker Noon

REST 和 GraphQL 之间的区别,就如左图 Redux + REST 之间的对话与右图 Apollo + GraphQL 的对话的区别(图片来源:Hacker Noon)(大图

15. 你会使用 AMP 或 Instant Articles 吗?

根据你的组织的优先级和策略,你可能须要考虑使用 Google 的 AMP 或者 Facebook 的 Instant Articles 或者 Apple 的 Apple News。若是没有它们,你也得到良好的性能,但 AMP 确实提供了一个可靠的性能框架和免费的内容分发网络(CDN),而 Instant Articles 将提升你在 Facebook 上的可见性和性能。

对于用户来讲, 这些技术最直观的的好处是保证了性能。 因此比起“正常“的和可能膨胀的页面,有时用户甚至更喜欢 AMP/Apple News/Instant Pages 连接。对于处理大量第三方内容的内容繁重的网站,这些选项可能有助于大幅加快渲染时间。

除非他们不这样作。例如,根据 Tim Kadlec的说法,“AMP 文档每每比同行更快,但并不必定意味着页面具备高性能。在性能方面,AMP 不是最大的差别。”

站长的好处显而易见:这些格式在各自平台上的可发现性以及搜索引擎的可见性提升。你也能够经过重复使用 AMP 做为 PWA 的数据源来构建渐进式 web APM。至于缺点?显然,由于各个平台的不一样的要求和限制,开发人员须要对他们的内容,在不一样平台制做和维护不一样的版本,若是是 Instant Articles 和 Apple News 没有实际的URL(感谢 Addy,Jeremy)。

16. 明智地选择你的 CDN

根据你拥有的动态数据量,你能够将内容的某些部分“外包”到 静态站点生成器,将其推送到 CDN 并从中提供静态版本,从而避免数据库请求。你甚至能够选择基于 CDN 的静态托管平台,经过交互式组件丰富你的页面做为加强功能(JAMStack)。事实上,其中一些生成器(如 Reats 之上的 Gatsby)其实是网站编译器,提供了许多自动优化功能。随着编译器随着时间的推移添加优化,编译后的输出随着时间的推移变得愈来愈小,愈来愈快。

请注意,CDN 也能够提供(和卸载)动态内容。所以,没必要将CDN限制为只有静态文件。仔细检查你的 CDN 是否执行压缩和转换(例如,在格式,压缩和边缘大小调整方面的图像优化),对 servers workers 的支持,包括边缘,在 CDN 边缘组装页面的静态和动态部分(即最接近用户的服务器)和其余任务。

注意:基于 Patrick Meenan 和 Andy Davies 的研究,HTTP/2 在许多 CDN 上被破坏,因此咱们不该该对那里的性能提高过于乐观。

[译] 2019 前端性能优化年度总结 — 第一部分
[译] 2019 前端性能优化年度总结 — 第二部分
[译] 2019 前端性能优化年度总结 — 第三部分
[译] 2019 前端性能优化年度总结 — 第四部分
[译] 2019 前端性能优化年度总结 — 第五部分
[译] 2019 前端性能优化年度总结 — 第六部分

若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索