2018 前端性能检查表

原文地址:http://www.smashed.by/perf-checklist 作者 | Vitaly Friedman 译者 | OpenWeb开发者 三三

众所周知,性能十分重要。然而,我们真的知道性能瓶颈具体在哪儿吗?是执行复杂的 JavaScript,下载缓慢的 Web 字体,巨大的图片,还是卡顿的渲染?研究摇树(Tree Shaking),作用域提升(Scope Hoisting),或是各种各样的与 IntersectionObserver、Clients Hints、CSS containment、HTTP/2 和 Service Worker 一同工作的华丽的加载模式真的有价值吗?最重要的是,我们从哪里开始优化性能,以及我们如何建立长期的性能文化呢?

以前,性能往往只是事后的想法。通常直到项目最后的时候才会被考虑,然后被归结为压缩、合并、静态资源优化或者对服务器配置文件的一些细微调整。现在回想起来,事情似乎已经发生了很大的变化。

性能不仅仅是一个技术问题:它很重要,而且当把它引入到工作流时,设计决策必须根据其性能影响来决定。我们必须不断的测量、监视和改进性能,而且 Web 日益复杂的情况带来了新的挑战,使得性能指标难以被跟踪,因为性能指标将因设备、浏览器、协议、网络类型和延迟(CDN、运营商、缓存、代理、防火墙、负载平衡器和服务器都在其中发挥作用)而有很大差异。

因此,如果我们创作一个在提高性能时必须牢记的所有事项的概述——从流程的一开始到网站的最终发布——这样的列表将是什么样子?下面就是 2018 前端性能检查表(但愿不偏不倚和足够客观)——说明您可能需要考虑的问题,以确保您的站点响应时间快、用户交互流畅,并且不会用尽用户的带宽。

下面是您可能需要考虑的前端性能问题的概述,以确保您的响应时间快速而流畅。

(译注:原文详细地阐述了文中所涉及的所有优化策略的原理和来龙去脉。此处仅翻译了原文中附带的 PDF 检查表文件,意在提供一个快速、简洁的性能优化清单。)

一、准备:规划和指标

01 建立性能文化

只要团队之间没有协作,高性能就无法长期维持。研究用户反馈中常见的抱怨,看看提高性能是否可以帮助缓解其中一些问题。用真实数据来建立适合自己的案例和模型。在设计过程中就开始规划加载顺序和权衡。

02 选择正确的性能指标

并非每个指标都同等重要。研究最重要的度量标准:一般而言,它与您开始渲染最重要像素的速度以及提供输入响应的速度有关。根据客户的感受确定页面加载的优先级。可交互时间、页面大标题元素的渲染时间、首次有效绘制时间(FMP)、速度指数(Speed Index)一般都很重要。

03 比你的竞争对手快至少 20%

收集代表您受众的设备上的数据。在数据来源上,真实设备比模拟数据更好。选择一台 Moto G4、中端三星设备或者 Nexus 5X 等性能良好的中端设备。或者,也可以通过在电脑上,通过设置网络限速(例如:150ms RTT,1.5Mbps 下载,0.7Mbps 上传)和 CPU 限速(5 倍慢速)以模拟移动体验。最后在常规 3G、4G 和 Wi-Fi 之间切换。收集数据、设置电子表格、将指标提高 20% 并设置目标(即,“性能预算”)。

04 把这张检查表分享给你的同事

确保团队中的每个成员都熟悉该清单。每一个决策都涉及性能问题,前端开发人员的积极参与将使您的项目受益匪浅。将你的性能预算映射到设计决策上。

二、制定现实的目标

05 100 毫秒的响应时间 + 每秒60帧

每帧动画应在少于 16 毫秒(理想情况下为 10 毫秒)内完成,从而达到每秒 60 帧(1 秒 ÷ 60 = 16.6毫秒)。保持乐观,明智地利用空闲时间。对于像动画这样的高压点,只要能,就不要做任何其它事情。预计输入延迟时间(Estimated Input Latency)应低于 50 毫秒。

06 速度指数(SpeedIndex)小于 1250,可交互时间(Time-To-Interactive)在 3G 上小于 5 秒

目标是在 1 秒内(在高速网络下)完成首次绘制(FMP),速度指数(SpeedIndex)低于 1250 毫秒。考虑速度基线是一台有着 3G 网络的,价格为 200 美元左右的 Android 手机(译注:国产千元机水平),那么可以以 400 毫秒 RTT 和 400kb/s 的传输速度进行网络模拟,以达成可交互时间(Time-To-Interactive)小于 5 秒,第二次打开的速度低于 2 秒。尽你所能地降低这些指标。

07 核心块 = 15kb,关键文件 < 170 kb

HTML 的前 14~15kb 是最关键的核心块(chunk),也是整个文件中唯一可以在第一个 RTT 内被下载的部分。要实现上述目标,请设定关键文件的最大尺寸“预算”。170kb gzip 后的文件(原始文件尺寸 0.8~1mb),在普通手机上可能需要 1 秒才能解析和编译完成。

三、定义环境

08 选择并设置你的构建工具

不要太注意所谓的“酷”。只要您能够快速获得结果,而且在维护构建过程上没有问题就很好了。

09 渐进增强

首先设计和构建核心功能,然后再在此基础上为功能强大的浏览器的高级功能增强效果,从而创建弹性的体验。如果您的网站在性能差、网络差的机器上还能运行得比较快,那在性能好、网络棒的机器上只会运行得更快。

10 设定硬性的性能基准

用 JavaScript 实现交互效果的成本相当高昂。170kb 的尺寸预算已经包含了核心的 HTML / CSS / JavaScript、路由、状态管理、工具函数、框架还有产品逻辑,因此,请彻底检查我们选择的框架的网络传输成本、解析 / 编译时间和其运行时的时间成本。

11 圣战止于智者:Angular, React 还是 Ember

并不是每个项目都需要框架。但是如果你的项目需要框架,那么最好选择使用一个支持服务器端渲染(SSR)的框架。在使用框架之前,请确保在移动设备上以服务器端渲染和客户端渲染两种模式来评估框架的启动时间。了解您将依赖的框架的具体细节。了解 PRPL 模式和 App Shell 模型。

12 你会使用 AMP 或者 Instant Articles 吗

(译注:AMP 为 Google 的开源项目,意在以组件化的形式以提升移动设备对网站的访问速度;Instant Articles 是 Facebook 的协议,意在通过渲染页面的精简版本以提升页面在 Facebook App 内的打开速度。在国内,MIP 是和 AMP 类似的解决方案。)

没有它们,你也可以获得良好的性能。但是 AMP 提供了一个可靠的性能框架,有免费的 CDN ,而 Instant Articles 将提高你在 Facebook 上的知名度和性能。你也可以构建一个渐进式 AMP(译注:Progressive Web AMP,PWA 和 AMP 的结合体)。

13 选择合适的 CDN

您可以将部分内容“外包”给静态站点生成器,然后将其推送到 CDN,并从CDN 提供静态版本,从而避免数据库请求(即 JAMStack)。当然,这取决于您拥有的动态数据量。仔细检查 CDN 是否为您执行了内容压缩和转换、智能 HTTP/2 和边缘端包含(ESI, edge-side includes)。

四、优化构建

14 合理安排优先级

把你所有的静态资源(JavaScript,图片,字体,第三方脚本,尺寸大的模块)列成一个表,然后把它们按优先级分成三组:基本核心功能(老浏览器也能浏览的核心内容)、增强体验效果(为现代浏览器设计的强大功能和丰富体验)、附加功能(不一定需要并且可以惰性加载的资源,比如字体、轮播脚本、视频播放器、分享按钮等)。

15 使用“符合标准”技术

(译注:“符合标准”技术(cutting-the-mustard technique)是 BBC News 开发者博客提出的,一种基于浏览器特性来检测其支持程度,并以此选择要加载哪些功能的技术。)

对老旧的浏览器,仅输出核心功能代码;对现代浏览器输出增强的功能代码。严格按标准加载静态资源:直接加载核心代码,在 DOMContentLoaded 事件中加载增强代码,并在 load 事件中加载剩下的代码。注意:廉价的 Android 手机虽然很符合标准,但这些手机的内存和 CPU 性能有限。因此,您可能需要使用读取设备内存大小的 JavaScript API 来检测设备性能,只有不支持的时候才按“符合标准”技术来。

16 减少 JavaScript 体积

由于解析 JavaScript 很耗时,所以请尽可能的减少 JavaScript 的体积。在构建 SPA 时,您可能需要用一定时间初始化应用程序之后,才能开始渲染页面。寻找可以加快初始渲染事件的模块和技术(在低端移动设备上,这可以轻松将速度提高 2-5 倍)。彻底检查每一个 JavaScript 依赖,以找出谁在消耗初始化的宝贵时间。

17 使用微优化和渐进式启动

使用服务器端渲染来获得快速的首次有效绘制时间(FMP),但也在页面里输出一些最小功能的 JavaScript 来保持交互时间(TTI)接近首次有效绘制时间(FMP)。然后,如果有需要或者有多余的时间,才开始启动应用程序的非必要部分。在加载时显示一个骨架屏幕,而不是“加载中”动画。

18 使用摇树和代码分割

使用摇树(Tree Shaking)技术和代码分割(Code Splitting)技术以减少代码体积。

摇树(Tree Shaking)技术是一种通过丢弃未使用的代码以在构建过程清理代码的方法。代码分割(Code Splitting)技术将您的代码拆分为按需加载的“chunks(块)”。作用域提升(Scope Hoisting)技术使得链式的依赖能被无缝地转换成行内函数。通过 WebPack 将上述技术用于您的代码。使用 AOT 编译器(译注:例如 Closure Compiler)将一些客户端计算移到服务端。

19 异步加载 JavaScript

作为开发者,我们必须显式地使用 deferasync 属性来告诉浏览器不要等待脚本下载、开始渲染页面。如果你不需要关注 IE 9 及以下版本的浏览器,那么使用 defer 更好;否则,使用 async 更好。使用静态的分享按钮、静态链接交互式地图而不是使用第三方库。

20 HTTP 缓存头是否设置好了

重新检查你是否正确的设置了 Expires, Cache-Control, Max-Age 等 HTTP 缓存控制响应头。通常而言,一个资源要么只被缓存很短的时间(比如经常修改的资源),要么永久缓存(比如不会被更改的那种资源)。使用专为带哈希指纹的静态文件设计的响应头 Cache-Control: imuutable 以避免浏览器重新请求文件。

五、静态资源优化

21 是否使用了 Brotli 或 Zopfli 压缩

Brotli 是一种新的无损压缩格式。现在,所有的现代浏览器都支持它。它比 Gzip 和 Deflate 压缩率更高,压缩非常慢,但是解压速度很快。使用最高压缩比的 Brotli+Gzip 预压缩静态文件,并使用 1~4 级的 Brotli 实时压缩动态内容。也顺便检查一下 CDN 是否支持 Brotli。或者,你也可以试试在不常变化的资源上使用 Zopfli —— 它将数据用 Deflate、Gzip 和 Zlib 格式压缩,并且被设计为一次压缩、多次下载。

22 图片是否被正确优化

尽可能使用通过 srcsetsizes 元素实现的响应式图片。使用 WebP 格式的图片;这可通过 标签配合 JPEG fallback,或者通过 Accept 请求头来实现。对于核心图片,使用渐进式的 JPEG 并用高斯滤镜模糊掉不重要的部分。

23 Web Font 是否被正确优化

您使用的 Web Font 很可能包含未真正被使用的执行和额外的特性。制作字体的子集(译注:仅包含部分文字的字体,如 fontmin 等方案)。优先使用 WOFF2 并使用 WOFF 作为后备。立即使用后备字体显示文字、异步加载字体(例如,使用 loadCSS),然后再切换字体。同时也考虑本地操作系统中已经安装了的字体。不要忘记在 CSS 中写 font-display: optional;如果你无法从您的服务器加载字体,请记得使用 Font Load Events。

六、分发优化

24 快速推送核心 CSS

将所有首屏渲染所需要的 CSS 放在一起,然后方法在 标签中。考虑有选择的内联的方法。或者,使用 HTTP/2 服务端推送;但这样你可能需要构建一个可感知缓存的 HTTP/2 服务端推送机制。

25 使用 babel-preset-env 以仅转译 ES2015+ 特性

由于 ES2015 已被广泛支持了,您可以考虑使用 babel-preset-env 以仅转译现代浏览器不支持的 ES2015+ 特性。然后你可以编译两份,一份是 ES6 ,另一份是 ES5。使用

你可能感兴趣的:(2018 前端性能检查表)