[译] 网络现状:性能提高指南

网络现状:性能提高指南

互联网正在爆发式地增加,咱们建立的 Web 平台也是如此。咱们一般都没有考虑到用户网络的连通性和使用情景。即便是万维网现状的一瞥,也能够看出咱们尚未创建起同理心和对形势变化的认知,更不用说对性能的考虑了。javascript

那么,现今的网络情况是怎样的呢?php

地球上 74 亿人口中,只有 46% 的人可以上网,平均网络速度为 7Mb/s。更重要的是,93% 的互联网用户都是经过移动设备上网的 —— 不去迎合手持设备是不可原谅的。数据每每比咱们想象中要昂贵得多 —— 购买 500MB 数据的价格在德国要为此工做 1 个小时,而在巴西须要 13 个小时(更多有趣的统计能够看看 Ben Schwarz《泡沫破灭:真实的性能》)。css

咱们的网站表现得也不尽如人意 —— 平均体积大概是初版 Doom 游戏的大小(3MB 左右)(请注意,为了统计准确度,须要使用中位数,推荐阅读 Ilya Grigorik《“平均页面”是一个神话》。中位数统计出的网站体积目前为 1.4MB)。图片能够轻松占用 1.7MB,而 JavaScript 平均为 400KB。不只仅只有 Web 平台,本地应用程序也有一样的问题,你是否遇到过为了修复某些 bug,不得不下载 200MB 的应用呢?html

技术人员常常会发现本身处于特权地位。拥有新型高端的笔记本、手机和快速的网络链接。咱们很容易忘记,其实并非每一个人都有这样的条件(实际上只有少部分人而已)。前端

若是咱们只站在本身而不是用户的角度来构建 web 平台,那这将致使糟糕的用户体验。java

咱们如何经过在设计和开发中考虑性能来作得更好呢?react

资源优化

最能明显提高性能但未被充分利用的方式是,从了解浏览器如何分析和处理资源开始。事实证实,当浏览器解析和当即肯定资源的优先级时,在资源发现方面表现得很是不错。下面是关于关键请求的解释。android

若是请求包含用户视口渲染所需的资源,那该请求就是关键请求。webpack

对于大多数网站,关键请求能够是 HTML、必要的 CSS、LOGO、网络字体,也多是图片。事实证实,在大多数状况下,当资源被请求时,许多其余不相关的(JavaScript、追踪代码、广告等)也被请求了。不过咱们可以经过仔细挑选重要资源,并调整它们的优先级来避免这种状况发生。ios

经过 <link rel ='preload'>,咱们能够手动强制设置资源的优先级,来确保所指望的内容按时渲染。这种技术能够明显改善“交互时间”指标,从而使最佳用户体验成为可能。

因为相关资料的缺少,关键请求对许多人来讲彷佛仍然是一个黑盒子。幸运的是,Ben Schwarz 发表了一篇很是全面且通俗易懂的文章 —— 《关键请求》。另外,你也能够查看 Addy 关于预加载的文章 —— 《Chrome 中的预加载和优先级》

在 Chrome 开发者工具中启用优先级
在 Chrome 开发者工具中启用优先级

🛠 要追踪优先处理请求的效果,你可使用 Lighthouse 性能检测工具和关键请求链路评测,或者查看 Chrome 开发者工具网络标签下的请求优先级。

📝 通用性能清单

  1. 主动缓存
  2. 启用压缩
  3. 优先关键资源
  4. 使用 CDN

图片优化

页面传输的大部分数据一般都是图片,所以优化图片能够带来很大的性能提高。有许多现有的策略和工具能够帮助咱们删除多余的字节,但首先要问的是:“图片对于传达后续的信息和效果相当重要吗?”。若是能够移除,不只能够节省带宽,还能够减小请求。

在某些状况下,咱们能够经过不一样的技术来实现一样的效果。CSS 有不少具备艺术性的属性,例如阴影、渐变、动画和形状,这就容许咱们用具备合适样式的 DOM 元素来替代图片。

选择正确的格式

若是必须使用图片,那肯定哪一种格式比较合适是很重要的。通常都在矢量图和栅格图之间进行选择:

  • 矢量图形:与分辨率无关,文件一般比较小。特别适用于 LOGO、图标和由简单图形(点、线、圆和多边形)组成的图片。
  • 栅格图像:表现内容更丰富。适用于照片。

作出上面的决定后,有这样的几种格式供咱们选择:JPEG、GIF、PNG-八、PNG-24 或者最新的格式,例如 WEBP 或 JPEG-XR。既然有这么多的选择,那如何确保咱们选择的正确性呢?如下是找到最佳格式的基本方法:

  • JPEG:色彩丰富的图片(例如照片)
  • PNG–8:色彩不是很丰富的图片
  • PNG–24:具备部分透明度的图片
  • GIF:动画图片

Photoshop 在图片导出时,能够经过一些设置来对上述格式的图片进行优化,例如下降质量、减小噪点或者颜色的数量。确保设计师有性能实践的意识,并经过正确的优化预设来准备合适的图片。若是你想了解更多关于如何开发图片的信息,能够阅读 Lara Hogan《速度与激情:以网站性能提高用户体验》

尝试新格式

有这样几种由浏览器厂商开发的新图片格式:Google 的 WebP,Apple 的 JPEG 2000 和 Microsoft 的 JPEG-XR。

WebP 是最具备竞争力的,支持无损和有损压缩使得它被普遍应用。无损 WebP 比 PNG 小 26%,比 JPG 小 25-34%。74% 的浏览器支持率及降级方案使它能够安全地被使用,最多可节省 1/3 的传输字节。JPG 和 PNG 能够经过 Photoshop 和其余图像处理程序,也可使用命令行(brew install webp)将其转换为 WebP。

若是你想探索这些格式之间的视觉差别,我推荐这个在 Github 上不错的示例

使用工具和算法进行优化

即使使用了高效的图片格式也须要后续的处理和优化。这一步很重要。

若是你选择了体积相对较小的 SVG,它们也须要被压缩。SVGO 是一个命令行工具,能够经过剥离没必要要的元数据来快速优化 SVG。另外,若是你喜欢 Web 界面或者因为操做系统的限制,也可使用 Jake ArchibaldSVGOMG。因为 SVG 是基于 XML 的格式,因此它也能够被服务端 GZIP 压缩。

ImageOptim 是大多数其余图片格式的绝佳选择,它将 pngcrush、pngquant、MozJPEG、Google Zopfli 等一些不错的工具打包进了一个综合的开源包里面。做为一个 Mac OS 应用程序、命令行界面和 Sketch 插件,ImageOptim 能够轻松地用于现有的工做流中。大多数 ImageOptim 依赖 CLI 均可以在 Linux 或者 Windows 平台上使用。

若是你倾向于尝试新兴的编码器,今年早些时候,Google 发布了 Guetzli —— 一个源于他们对 WebP 和 Zopfli 研究的开源算法。Guetzli 能够生成比任何其余可用的压缩方法少 35% 体积的 JPEG。惟一的缺点是:处理时间慢(每百万像素的 CPU 时间为一分钟)。

选择工具时,请确保它们能达到预期并适合团队的工做流。最好能自动化优化,这样全部图片都是优化过了的。

响应式图片

十年前,也许一种分辨率就能知足全部的场景,但随着时代的变化,响应式网站现今已大相径庭。这就是为何咱们必须特别当心地实施咱们精心优化的视觉资源,并确保它们适应各类视口和设备。幸运的是,感谢响应式图像社区组织,经过 picture 元素和 srcset 属性(都有 85%+ 的浏览器支持率),咱们能够完美地作到。

srcset 属性

srcset 在分辨率切换场景中表现得很是不错 —— 当咱们想根据用户的屏幕密度和大小显示图片时。根据 srcsetsizes 属性中一些预约义的规则,浏览器将会根据视口选择最佳的图片进行展现。这种技术能够节省带宽和减小请求,特别是对于移动端用户。

srcset 属性使用示例
srcset 属性使用示例

picture 元素

picture 元素和 media 属性旨在更容易地通往艺术殿堂。经过为不一样的条件提供不一样的来源(经过 media-queries 测试),不管分辨率如何,咱们始终能聚焦在最重要的图像元素上。

picture 元素使用示例
picture 元素使用示例

📚 阅读 Jason Grigsby《响应式图片 101》 能够全面地了解这两种方式。

使用图片 CDN

图片性能的最后一步就是分发了。全部资源均可以从使用 CDN 中受益,但有一些特定的工具是专门针对图片的,例如 Cloudinary 或者 imgx。使用这些服务的好处远不止于减小服务器流量,它还能够显著减小响应延迟。

CDN 能够下降重图片站点提供自适应和高性能图片的复杂度。他们提供的服务各不相同(价格也不一样),可是大多数均可以根据设备和浏览器进行尺寸调整、裁剪和肯定最合适的格式,甚至更多 —— 压缩、检测像素密度、水印、人脸识别和容许后期处理。借助这些强大的功能和可以将参数附到 URL 中,使得提供以用户为中心的图片变得垂手可得了。

📝 图片性能清单

  1. 选择正确的格式
  2. 尽量使用矢量图
  3. 若是变化不明显,则下降质量
  4. 尝试新格式
  5. 使用工具和算法进行优化
  6. 学习 srcset 属性和 picture 元素
  7. 使用图片 CDN

优化网络字体

使用自定义字体的能力是一个很是强大的设计工具。但权利越大,责任就越大。68% 的网站正在使用网络字体,而这种资源是最大的性能瓶颈之一(很容易平均达到 100KB,这取决于字体的各类形态和数量)。

即便体积不是最重要的问题,但不可见文本闪现(FOIT)是。当网络字体在加载中或者加载失败时,就会发生 FOIT,这会致使空白页面,从而形成内容没法访问。这可能值得咱们仔细检查是否须要网络字体。若是是这样,有一些策略能够帮助咱们减轻对性能的负面影响。

选择正确的格式

有四种网络字体格式:EOT、TTF、WOFF 和近期的 WOFF2。TTF 和 WOFF 被普遍使用,拥有超过 90% 的浏览器支持率。根据你所针对的支持状况,使用 WOFF2 可能最安全,并为老版本浏览器降级使用 WOFF。使用 WOFF2 的优势是一整套自定义的预处理和压缩算法(如 Brotli)能够 缩小 30% 的文件大小和改进过的解析性能。

@font-face 中定义网络字体的来源时,使用 format() 提示来指定应该使用哪一种格式。

若是你正在使用 Google 字体或者 Typekit 字体,他们都实施了一些策略来减轻对性能的影响。Typekit 全部套件如今都支持异步来预防 FOIT,而且容许其 JavaScript 套件代码的缓存期限延长 10 天(而不是默认的 10 分钟)。Google 字体能够根据用户设备自动提供最小的文件。

字体选择评测

不管是否自托管,字体的数量、体积和样式都将明显影响性能。
理想状况下,咱们只须要一种包括常规和粗体的字体。若是你不肯定如何选择字体,能够参考 Lara Hogan 的《美学与性能》

使用 Unicode-range 子集

Unicode-range 子集容许将大字体分割成较小的集合。这是一个相对先进的策略,但它可能会明显地减小字体体积,特别是在针对亚洲语言的时候(你知道中文字体的平均字形数是 20,000 吗?)。第一步是将字体限制为必要的语言集,例如拉丁语、希腊语或西里尔语。若是网络字体只是作 LOGO 类的使用,那彻底可使用 Unicode-range 描述符来选择特定的字符。

Filament Group 发布的开源命令行工具 glyph hanger 能够根据文件或 URL 生成须要的字形列表。或者,基于 web 的 Font Squirrel Web Font Generator,它提供高级子集和优化选项。若是使用 Google 字体或者 Typekit,他们在字体选择界面都提供了语言子集的选择,这使得肯定基本子集更容易。

创建字体加载策略

字体是阻塞渲染的 —— 由于浏览器须要首先建立 DOM 和 CSSOM;网络字体用于与现有节点相匹配的 CSS 选择器以前,它都不会被下载。这种行为显然延迟了文本的渲染,一般都会致使前面提到的不可见文本闪现(FOIT)。在较慢的网络和移动设备上,FOIT 则更加明显。

实施字体加载策略能够避免用户没法访问内容。一般,无样式文本闪现(FOUT)是最简单和最有效的解决方案。

font-display 是一个新的 CSS 属性,提供了一个不依赖 JavaScript 的解决方案。不幸的是,它只被部分支持(Chrome 和 Opera),Firefox 和 WebKit 目前在开发中。尽管如此,它能够而且应该与其余字体加载机制结合使用。

font-display 属性示例
font-display 属性示例

幸运的是,Typekit 的网络字体加载器Bram Stein字体观察者 能够帮助咱们管理字体的加载行为。此外,Zach Leatherman 是网络字体性能的专家,他发布的《字体加载策略综合指南》将帮助你为你的项目选择正确的方法。

📝 网络字体性能清单

  1. 选择正确的格式
  2. 字体选择评测
  3. 使用 Unicode-range 子集
  4. 创建字体加载策略

优化 JavaScript

目前,JavaScript 包的平均大小为 446KB,这使得使其成为第二大致积类型的资源(仅次于图片)。

咱们可能没有意识到,咱们所钟爱的 JavaScript 隐藏着更加危险的性能瓶颈。

监控 JavaScript 传输

优化传输只是抗衡页面臃肿的一种方法。JavaScript 下载后,必须由浏览器进行解析、编译和运行。浏览一些热门的网站,咱们会发现,gzip 压缩后的 JS 在解压以后至少变大三倍。实际上,咱们正在发送一大堆代码。

1MB JavaScript 在不一样的设备上的解析时间。图片来源于 Addy Osmani 的《JavaScript 启动性能》

分析解析和编译时间,对于理解应用程序什么时候准备好进行交互相当重要,这些时间因用户设备的硬件能力而异。解析和编译的时间会很容易地在低端手机上高出 2-5 倍Addy 的研究代表,一个应用程序在普通手机上须要 16 秒才能达到可交互状态,而在桌面上是 8 秒
分析这些指标相当重要,幸运的是,咱们能够经过 Chrome 开发者工具来完成。

在 Chrome 开发者工具中审查解析和编译过程
在 Chrome 开发者工具中审查解析和编译过程

请务必阅读 Addy Osmani 在《JavaScript 启动性能》文中的详细总结。

移除没必要要的依赖

现今的包管理方式能够很容易地隐藏依赖包的数量和大小。webpack-bundle-analyzerbundle-buddy 是很好的可视化工具,能够帮助咱们识别出重复代码、最大的性能瓶颈以及过期和没必要要的依赖包。

Webpack bundle analyzer 的示例
Webpack bundle analyzer 的示例

经过 VS CodeAtom 中的 Import Cost 扩展,咱们能够明显知晓导入包的大小。

VS Code 中的 Import Cost 拓展
VS Code 中的 Import Cost 拓展

实施代码分割

只要有可能,咱们就应该只提供用户体验所必需的资源。向用户发送一个完整的 bundle.js 文件,包括他们可能永远看不到的交互效果的处理代码,这不太理想(试想一下,在访问着陆页时,下载了处理整个应用程序的 JavaScript)。一样,咱们不该处处提供针对特定浏览器或用户代理的代码。

Webpack 是最受欢迎的打包工具之一,默认支持代码分割。最简单的代码分割能够按页面实施(例如着陆页面的 home.js,联系页面的 contact.js 等)。但 Webpack 提供了比较少的高级策略,例如动态导入或者懒加载,这可能值得研究。

考虑框架选择

JavaScript 的前端框架突飞猛进。根据 2016 年的 JavaScript 现状调查,React 是最受欢迎的。仔细评估架构选型可能会发现,你能够采用更为轻量级的替代方案,例如 Preact(须要注意的是,Preact 并非一个完整的 React 从新实现,它只是一个具备高性能,功能更轻的虚拟 DOM 库)。一样,咱们能够将较大的库替换为更小的替代方案 —— moment.js 换成 date-fns(或者在特定状况下,删除 moment.js 中未使用的 locales)。

在开始一个新项目以前,有必要肯定什么样的功能是必需的,并为你的需求和目标选择性能最好的框架。有时这可能意味着选择写更多的原生 JavaScript。

📝 JavaScript 性能清单

  1. 监控 JavaScript 传输
  2. 移除没必要要的依赖
  3. 实施代码分割
  4. 考虑框架选择

性能追踪,前进之路

在大多数状况下,咱们讨论过的一些策略会对咱们正在打造的产品的用户体验产生积极的变化。性能多是一个棘手的问题,有必要长期跟踪咱们调整的效果。

以用户为中心的性能指标

卓越的性能指标,旨在尽量接近描绘的用户体验。以往的 onLoadonContentLoaded 或者 SpeedIndex 对于用户多久能与页面进行交互给出的信息很是少。当仅关注资源传输时,咱们很难量化感知获得的性能。幸运的是,有一些时间能够很好地描述内容的可视性和互动性。

这些指标是白屏时间、首次有效渲染、视觉完整和可交互时间。

  • First Paint 白屏时间:浏览器从白屏到第一次视觉变化。
  • First Meaningful Paint 首次有效渲染:文字、图像和主要内容都已可见。
  • Visually Complete 视觉完整:视口中的全部内容均可见。
  • Time to Interactive 可交互时间:视口中的全部内容均可见,而且能够进行交互(JavaScript 主线程中止活动)。

这些时间和用户体验息息相关,所以能够做为重点进行追踪。若是可能,将它们所有记录,不然选择一两个来更好地监控性能。其余指标也须要关注,特别是咱们发送的字节数(优化和解压缩)。

设置性能预算

全部数据可能会很快变得使人困惑和难以理解。没有可执行的目标,很容易迷失咱们最初的目的。几年前,Tim Kadlec 写过关于《性能预算》的概念。

遗憾的是,没有什么神奇的公式能够设置它们。性能预算一般归结为竞争分析和产品目标,而这是每一个业务所独有的。

设定预算时,重要的是要有明显的差别,一般状况下,至少要有 20% 的改善。实验和迭代你的预算,能够参考 Lara Hogan 的使用性能预算来接近新设计

使用性能预算计算器或者 Browser Calories Chrome 拓展程序来帮助你建立预算。

持续监控

性能监控应该是自动化的,市面上有不少提供全面报告的强大工具。

Google Lighthouse 是一个开源项目,它能够审查性能、可访问性、PWA 等。你能够在命令行中或者直接在 Chrome 开发者工具中使用它。

Lighthouse 性能审查示例
Lighthouse 性能审查示例

对于持续的追踪,能够选择 Calibre,它提供的性能预算、设备仿真、分布式监控和许多其余功能是咱们不在构建本身的性能套件上花费大量精力是完成不了的。

使用 Calibre 进行全面的性能追踪
使用 Calibre 进行全面的性能追踪

不管你在哪里追踪,请确保数据对于整个团队或者小型组织里的整个业务线都是透明和可访问的。

性能是共同的责任,不只仅是开发团队 —— 咱们都应对所建立的用户体验负责,无论是什么角色或职级。

在产品决策或者设计阶段,提倡速度和创建协做流程以发现可能的瓶颈是很是重要的。

创建性能意识和同理心

关心性能不只仅是一个业务目标(但若是你须要经过销售统计数据来进行销售,那可使用 PWA 统计)。这关乎于基本的同理心,并把用户的最大利益放在第一位。

做为技术人员,咱们的责任是,不要让用户的注意力和时间放在等待页面上。咱们的目标是,创建有时间观念和以人为本的工具

提倡性能意识应该是每一个人的目标。让咱们抱着性能和同理心,为全部人创建一个更好、更有意义的将来吧。


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

相关文章
相关标签/搜索