(译)2019年前端性能优化清单 — 中篇

  • (译)2019年前端性能优化清单 — 上篇
  • (译)2019年前端性能优化清单 — 中篇
  • (译)2019年前端性能优化清单 — 下篇

目录

  • 资源优化
    • 17. 使用 Brotli 或 Zopfli 进行纯文本压缩
    • 18. 使用响应式图像和 WebP
    • 19. 图像是否已恰当优化
    • 20. 视频是否已恰当优化
    • 21. Web 字体是否已恰当优化
  • 构建优化
    • 22. 分清轻重缓急
    • 23. 考虑使用 cutting-the-mustard 技术
    • 24. 解析 JavaScript 是昂贵的,所以保持小
    • 25. 使用无用代码移除(Tree-shaking) ,作用域提升(Scope hoisting)和代码分割(Code-splitting)来减少有效负载
    • 26. 能否将 JavaScript 卸载到 Web Worker 中
    • 27. 能否将 JavaScript 卸载到 WebAssembl 中
    • 28. 您使用的是预编译器吗
    • 29. 仅将遗留代码提供给传统浏览器
    • 30. 您是否在 JavaScript 中使用差异化服务
    • 31. 通过增量解耦识别和重写遗留代码
    • 32. 识别并删除未使用的 CSS / JavaScript
    • 33. 修剪 JavaScript 依赖项的大小
    • 34. 您是否正在使用 JavaScript 块的预测预取
    • 35. 利用针对目标 JavaScript 引擎的优化
    • 36. 客户端渲染还是服务器端渲染
    • 37. 限制第三方脚本的影响
    • 38. 正确设置 HTTP 缓存头
  • 交付优化
    • 39. 异步加载 JavaScript
    • 40. 使用 IntersectionObserver 延迟加载昂贵的组件
    • 41. 逐步加载图像
    • 42. 快速推送关键 CSS
    • 43. 尝试重新组合 CSS 规则
    • 44. 流响应
    • 45. 考虑使组件连接/设备内存感知
    • 46. 考虑使您的组件设备具有内存感知能力
    • 47. 预热连接以加快传输速度
    • 48. 使用 Service workers 进行缓存和网络回退
    • 49. 您是否使用 CDN / Edge 上的 Service workers(例如,进行A / B测试)
    • 50. 您是否优化了渲染性能
    • 51. 您是否优化了渲染体验

资源优化

17. 使用 Brotli 或 Zopfli 进行纯文本压缩

在 2005 年,Google推出 了 Brotli,一个新的开源无损数据压缩格式,现在已经被 所有的现代浏览器所支持。实际上,Brotli 比 Gzip 和 Deflate 更有效。压缩速度可能会非常慢,但这取决于设置信息,可是缓慢的压缩过程会提高压缩率。它仍然可以快速解压缩,并且您还可以估算您网站的Brotli压缩成本。

只有当用户通过 HTTPS 访问网站时,浏览器才会采用。Brotli 现在还不能预装在某些服务器上,而且如果不自己构建 NGINX 和 UBUNTU 的话很难部署。不过这也并不难,而且它的支持即将到来,例如,从Apache 2.4.26开始 就可以使用它了。Brotli 得到了广泛的支持,许多 CDN 支持它( Akamai、AWS、KeyCDN、Fastly、Cloudlare、CDN77),您甚至可以在 还不支持它的CDN上 启用Brotli(与 service worker 一起)。

在最高级别的压缩下,Brotli 的速度会变得非常慢,以至于服务器在等待动态压缩资源时开始发送响应所花费的时间可能会使我们对文件大小的优化无效。但是,对于静态压缩,高压缩比的设置比较受欢迎—— (感谢 Jeremy!)

或者,你可以考虑使用 Zopfli的压缩算法,将数据编码为 DeflateGzipZlib 格式。Zopfli 改进的 Deflate 编码使得任何使用 Gzip 压缩的文件受益,因为这些文件大小比 用Zlib 最强压缩后还要小 3% 到 8%。问题在于压缩文件的时间是原来的大约 80倍。这就是为什么虽然 使用 Zopfli 是一个好主意但是变化并不大,文件都需要设计为只压缩一次可以多次下载的。

比较好的方法是你可以绕过动态压缩静态资源的成本。Brotli 和 Zopfli 都可以用于明文传输 —— HTML,CSS,SVG,JavaScript 等。

有什么方法呢?在最高等级和 Brotli 的 1-4 级动态压缩 HTML 使用Brotli+Gzip 预压缩静态资源。同时,检查 Brotli 是否支持 CDN,(例如KeyCDN,CDN77,Fastly)。确保服务器能够使用 Brotli 或 gzip 处理内容。如果你不能安装或者维护服务器上的 Brotli,那么请使用 Zopfli。

18. 使用 响应式图像 和 WebP

尽可能通过 srcsetsizes 元素使用响应式图片。也可以通过 元素使用 WebP格式的图像(Chrom,Opera,Firefox soon支持),或者一个 JPEG 的回调(见 Andreas Bovens 的 code snippet)或者通过使用内容协商(使用 Accept 头信息)。Ire Aderinokun 中也有一个关于 将图像转换为WebP非常详细的教程。

Sketch 本身就支持 WebP,并且 WebP 图像可以通过使用 WebP插件 从 PhotoShop 中导出。您也有 其他选择 可以使用。你可以使用 WordPress 或者 Joomla,也有其他可以轻松支持 WebP 的扩展,例如 Optimus 和 Cache Enabler 以及 Joomla自己支持的扩展(通过 Cody Arsenault)。

您需要注意的是,虽然WebP图像文件大小与 Guetzli和Zopfli相比大小都差不多,但格式 不支持像 JPEG 这样的渐进式渲染,这就是为什么用户在使用良好的旧 JPEG 时会更快地看到实际图像,尽管 WebP 图像可能在网络中加载速度会更快。使用 JPEG,我们可以用一半甚至四分之一的数据保证良好的用户体验,然后再加载其余的数据,而不会像WebP那样显示半空的图像。您的决定取决于您的目标:如果您使用WebP,那么将会减少网络的负载,如果使用JPEG,您将提高用户体验。

在 Smashing Magazine 上,我们使用后缀-opt作为图像名称—例如brotli-compression-opt.png;每当图像包含该后缀时,团队中的成员就会知道该图像已经被优化。还有 —— shamleless plug!-Jeremy Wagner 在 WebP上发表了一本Smashing书。

响应式图像断点生成器 自动生成图像和标记生成。

19. 图像是否已恰当优化

现在有一个至关重要着陆页,有一个特定的图片的加载速度非常关键,确保 JPEGs 是渐进式的并且使用Adept、mozJPEG(通过操纵扫描级来改善开始渲染时间)或者 Guetzli 压缩,谷歌新的开源编码器重点是能够感官的性能,并借鉴 Zopfli 和 WebP。唯一的不足是:处理的时间慢(每百万像素 CPU 一分钟)。至于 png,我们可以使用 Pingo 和 svgo,对于 SVG 的处理,我们使用 SVGO 或 SVGOMG。

每一个图像优化的文章会说明,但始终会提醒要保持矢量资源干净和紧密。确保清理未使用的资源,删除不必要的元数据,并减少图稿中的路径点数量(从而减少SVG代码)。(感谢,Jeremy!)

不过下面还有一些更好的方法:

  • 使用 Squoosh 以最佳压缩级别(有损或无损)压缩,调整大小和操作图像。
  • 使用 响应式图像断点生成器 或 Cloudinary 或 Imgix 等服务来自动优化图片。同样,在许多情况下,单独使用 srcsetsize 也会有很不错的效果。
  • 可以使用 映像堆 检查响应式标记的效率,这是一种命令行工具,也可以用来测量视口大小和设备像素比率的效率。
  • 延迟加载带有 lazysizes 的图像和iframe,这是一个库,可以检测页面上通过用户交互(或者我们将在稍后探索的IntersectionObserver)而触发的任何改变。
  • 格外注意那些会默认加载但可能永远不会显示的图像——例如carousels、accordions和image galleries。
  • 考虑通过根据媒体查询指定不同的图像显示尺寸来 交换具有sizes属性 的图像,例如操纵sizes以交换放大镜组件中的源。
  • 检查图像 下载的不一致性,以防止对前景和背景图片的意外下载。
  • 为了优化内部存储,你可以使用 Dropbox 新的 Lepton格式 进行压缩,平均将jpeg压缩22%。
  • 注意 aspect-ratio CSS 和 intrinsicsize-attribute 中的属性,它们允许我们为图像设置宽高比和size,因此浏览器可以提前预留一个预定义的布局槽,以 避免 在页面加载期间出现 布局跳转。
  • 如果你想使用其他方式,你可以尝试 Edge worker (一种基于CDN的实时过滤器)来剪切和重新排列HTTP/2流,从而更快地通过网络发送图片。Edge workers 使用您可以控制的块的JavaScript流(基本上它们是在CDN边缘上运行的可以修改流式响应的JavaScript),所以可以控制图像的传递。对于server worker 来说,为时已晚,因为您无法控制在线上的内容,但Edge workers 来说确实有效。因此,您可以在针对特定登录页面逐步保存的静态JPEG之上使用它们。

图像堆栈 输出的一个示例,这是一个命令行工具,用于测量视图大小和设备像素比的效率。

随着 客户端提示(client-hints) 的采用,响应图像的未来可能会发生巨大的变化。客户端提示是一个HTTP请求头字段,例如 DPRViewport-WidthWidthSave-DataAccept (指定图像格式首选项)等。它们通过告知服务器关于用户浏览器、屏幕、连接等的详细信息,然后服务器可以按照详细信息提供如合适格式、合适大小的图片来填充布局。通过客户端提示,我们可以发送一个将资源选择从HTML标记转移到客户端和服务器之间的请求-响应协商。

正如 Ilya Grigorik所指出的,客户端提示完成了图像——它们不是响应图像的替代方案。元素在HTML标记中提供必要的艺术方向控制。客户端提示为生成的图像请求提供注释,从而支持资源选择自动化。Service Worker在客户端上提供完整的请求和响应管理功能。例如,service Worker可以向请求添加新的客户端提示标头值,以重写URL并将图像请求指向CDN,根据连接和用户首选项等来调整响应。它不仅适用于图像资源,而且还是适用于几乎其他的所有请求。

对于支持客户端提示的客户端,可以在图像上 节省42%的字节,在70%以上的百分比上节省1MB以上的字节。在Smashing Magazine上,我们也可以测量 19-32%的改进。糟糕的是,客户端提示仍然需要 获得一些浏览器支持,Firefox正在考虑中。但是,如果同时提供正常响应图像标记和 客户端提示标记,那么浏览器将评估响应图像标记并使用客户端提示HTTP头请求适当的图像资源。

如果这样子做还不够的话。您还可以使用 多 背景 图像 技术 提高图像的性能。请记住,使用对比度 和模糊不必要的细节(或删除颜色)也可以减少文件大小。如果你需要在不影响图片质量的情况下放大一张小照片的话,可以考虑使用 Letsenhance.io。

到目前为止,这些优化只覆盖了基础。Addy Osmani已经发布了一份非常详细的 关于基本图像优化的指南,其中深入介绍了图像压缩和颜色管理的细节。例如,您可以模糊掉图像中不必要的部分(通过对它们应用高斯模糊过滤器)以减小文件大小,甚至可以删除颜色或将图像变为黑白,以进一步缩小图像尺寸。如果是背景图像,从Photoshop中导出0到10%质量的照片也是绝对可以接受的。奉劝大家 不要在网上使用JPEG-XR。

20. 视频是否已恰当优化

到目前为止,我们已经谈论了一些图片,但是我们一直没有说到GIF图片。坦白的说,如果不是加载影响渲染性能和宽带的重型动画GIF,建议最好切换到动画WebP(GIF是后备)或者用 循环HTML5 video 替换它们。是的,浏览器 处理 video 的速度很慢,而且与图像不同的是,浏览器不会预加载 video 内容,但 video 往往要比gif更轻更小。至少我们可以用 Lossy GIF,gifsicle 或 giflossy 来给GIF添加有损压缩。

早期测试表明,img 标签内的内嵌视频 显示速度提高了20倍,解码速度比相同大小的 GIF动图要 快7倍,另外文件大小尺寸也会优于GIF。尽管对 Safari技术预览版 的支持 已经 落实,但还远未被广泛采用,因为它 不会很快进入Blink。

Addy Osmani 建议用循环的内联视频来替换动画GIF。文件大小的差异很明显(节省了80%)。

然而,在这片充满好消息的土地上,视频格式多年来一直在大规模发展。很长一段时间以来,我们一直希望WebM能够成为规范所有这些格式的格式,而 WebP (基本上是 WebM 视频容器中的一个静态图像)将成为过时的图像格式的替代品。但是,尽管 WebP 和 WebM 最近 获得了 支持,可是他们没有什么实质性的突破。

2018年,开放媒体联盟(Alliance of Open Media)发布了一种名为 AV1 的新型视频格式。AV1 的压缩类似于 H.265 编解码器(H.264的演变),与后者不同的是,AV1是免费的。H.265的收费制使得浏览器厂商开始采用性能 相对较高 的 AV1: AV1(类似H.265)的压缩效果是WebP的两倍

AV1很有可能成为网络视频的终极标准。(图片来源: Wikimedia.org)

事实上,苹果目前使用的是 HEIF 格式和 HEVC (H.265),最新iOS上的所有照片和视频都以这些格式保存,而非JPEG格式。虽然 HEIF 和 HEVC (H.265) 还没有完全公开到网络上,但是 AV1 已经完全公开在网络上并且 正在获得浏览器支持。因此,AV1在您的 标记中添加源是合理的,因为所有浏览器供应商都在为支持AV1做准备。

目前,最广泛使用和支持的编码是H.264,由MP4文件提供服务,因此在提供文件之前,请确保使用 多通道编码 处理MP4 ,模糊了frei0r iirblur效果(如果适用)和 moov atom metadata 移动到文件的头部,而服务器 接受字节服务。Boris Schapira 为 FFmpeg 提供了最大限度优化视频的 标准说明。当然,提供WebM格式作为替代方案也会有所帮助。

视频播放性能本身就是一个故事,如果您想深入了解它,请阅读Doug Sillar关于 视频 和 视频传输最佳实践的最新实践系列,其中包括关于视频传输度量、视频预加载、压缩和流媒体的详细信息。

Zach Leatherman 的 字体加载策略综合指南 为更好的 web 字体交付提供了十几种选择。

21. Web 字体是否已恰当优化

首先需要问一个问题,你是否能不使用 UI 系统字体。 如果不可以,那么你有很大可能使用 Web 网络字体,会包含字形和额外的功能以及用不到的加粗。如果您使用的是开源字体,您可以向字体设计公司 获取 网络字体子集或子集,也可以使用 Glyphhanger 或 Fontsquirrel 对其进行子集化。您甚至可以使用 Peter Muller 的 subfont 将整个流程自动化,因为他是一个命令行工具,它通过静态地分析您的页面,然后生成最优的web字体子集,最后将它们注入到您的页面中。

WOFF2的支持 非常好,对于不支持WOFF2的浏览器,你可以使用 WOFF 和 OTF 作为不支持它的浏览器的备选。另外,从 Zach Leatherman 的 《字体加载策略综合指南》(代码片段也 可以作为Web字体 加载片段)中选择一种策略,并使用服务器缓存持久地缓存字体。

可能今天要考虑的更好的选择是 关键FOFT预加载 和 折中 方法。它们都使用两阶段渲染来逐步提供Web字体——首先是使用web字体快速准确地呈现页面所需的小超子集,然后加载其余的异步操作。不同之处在于,折中 技术仅在不支持 字体加载事件 时才异步加载polyfill ,因此默认情况下不需要加载polyfill。需要速战速决吗?Zach Leatherman有一个 23分钟的快速教程 和案例研究,以使您的字体优化。

通常,使用 preload 资源提示来预加载字体是一个好办法,但在标记中要包含关键CSS和JavaScript链接后的提示。否则,字体加载将在第一次渲染时造成损失。不过,有 选择性 地选择最重要的文件可能是一个好主意,比如那些对渲染至关重要的文件,或者那些可以帮助您避免可见和破坏性文本重拍的文件。一般来说,Zach建议 预加载每个系列的一到两种字体——如果字体不是很重要,那么建议延迟加载。

我相信没有人喜欢等待内容的显示。使用 font-display CSS描述符,我们可以控制字体加载行为,并使内容立即可读 (font-display: optional) 或几乎立即可读 (font-display: swap)。但是,如果您想 避免文本重排,我们仍然需要使用字体加载API,特别是对 重组 进行 分组,或者当您使用第三方主机时,除非您可以 将Google字体与Cloudflare Workers一起使用。谈到谷歌字体::可以考虑使用 Google -webfonts-helper,这是一种轻松自我托管Google字体的方式。如果可以的话,采用 始终自行托管自身项目的字体 的方式来获得最大程度的控制。

一般情况下,如果您使用font-display: optional,也可能不是一个好主意,因为preload会提前触发Web字体请求(如果您有其他需要获取的关键路径资源,则会导致网络拥塞)。使用preconnect可以实现更快的跨域字体的请求,但需要注意的是,preload从不同来源预载的字体wlll会导致网络占用。所有这些技术都包含在 Zach 的 Web字体加载方式 中。

此外,如果用户在可访问性首选项中启用了 Reduce Motion,或者选择了Data Saver模式(请参见 Save-Data header),或者当用户连接速度较慢时(通过 网络信息API),则最好选择退出Web字体(或至少是第二阶段渲染)。

要测量Web字体加载性能,请考虑 所有文本可见 度量标准(所有字体已加载且所有内容以 Web字体显示的时刻),以及首次渲染后的 Web字体重排计数。显然,两个指标越低,性能越好。重要的是要注意 可变 字体 可能需要 显著的性能考虑。它们为设计人员提供了更广阔的设计空间来选择字体,但它的代价是单个串行请求,而不是单个文件请求。单个请求可能会阻碍页面上的整个排版外观。但好消息是,当我们有了可变字体,在默认情况下只需要获得一个 reflow,而不需要 JavaScript 对重新绘制进行分组。

怎么才能是一个无漏洞的字体加载策略? 从font-display开始,然后到 Font Loading API,然后到 Bram Stein 的 Font Face Observer(感谢 Jeremy!)如果你有兴趣从用户的角度来衡量字体加载的性能, Andreas Marschke 探索了 使用 Font API 和 UserTiming API 进行 性能跟踪。

此外,不要忘记包含 font-display:optional 描述符来提供弹性和快速的字体回退,unicode-range 将大字体分解成更小的语言特定的字体,以及 Monica Dinculescu 的 字体样式匹配器 用来解决由于两种字体之间的大小差异,最大限度地减少了布局上的震动的问题。

构建优化

22. 分清轻重缓急

你应该知道优先处理什么。运行你所有静态资源(JavaScript、图片、字体、第三方脚本和页面中“昂贵的”模块,比如:轮播图、复杂的图表和多媒体内容),并将它们划分成组。

建立一个电子表格。针对传统浏览器定义基本的核心体验(即完全可访问的核心内容),针对多功能的浏览器定义增强的体验(即丰富的、完整的体验)和额外的体验(不是绝对需要的并且可以延迟加载的资源,如web字体、不必要的样式、轮播图、视频播放器、社交媒体按钮、大图片等)。不久前,我们发表了一篇关于 Improving Smashing Magazine的性能 的文章,上面有该方法的详细介绍。

我们在优化性能时候的优先级是:首先加载核心体验,然后是增强功能,最后才是附加功能。

23. 考虑使用 cutting-the-mustard 技术

现在,我们仍然可以使用 cut -the-mustard 技术 将核心体验传递给传统浏览器,并提高对现代浏览器的体验。该技术的 下一版本 将使用 ES2015 +

你可能感兴趣的:((译)2019年前端性能优化清单 — 中篇)