原文地址: https://blog.pragmatists.com/how-to-debug-front-end-optimising-network-assets-c0bfcad29b40
作者: Michał Witkowski
摘要:本文从性能监控、图片、网络字体和JS代码优化以及如何提升渲染阻塞资源的加载速度等方面列举了常见的前端优化方法。
性能是决定我们Web应用成功与否的重要因素。一开始,我们的Web应用体积较小,几乎没有开发者会关注于持续监控用户接收的数据大小以及所需时间。
如果你不曾做过性能监控,那么你的网站性能很可能还有提升的余地。这时就出现了一个问题,为了让用户能够感知到性能的提升,你应该做出哪些努力呢?
在下面的研究中,你可以了解到如何让用户感觉到加载时间发生了明显的变化,并且你至少要完成20%的任务,才能让用户注意到你为此付出的努力。 更多资料
接下来的文章分为6个部分:
如果你还有其他问题,请在评论中告知。我们的团队和读者们很乐意帮助你。
由于本系列都与Chrome Devtools有关,所以这次我们从Audit标签开始。它使用了Lighthouse。
打开Chrome Devtools,然后选择Audits标签,接着点击 Perform an audit...
,接着 Run audit
。
我决定只检查 Performance
和 Best practices
,因为我不关心 Progressive Web App
或 Accessibility
的结果。
译者注:这一步应该需要翻墙,不然会卡在lighthouse is warming up。
很好。只需要等待一会儿,我们就完成了性能检查并且把它当成衡量指标来提升网站的性能。Audits会把网页视图更改成移动版,对此你不需要担心有什么负面影响,因为这是Chrome的默认行为。另外,我强烈建议你使用Canary版Chrome的audits。Canary版能够监控桌面端网页,并且新增了一个节流的选项。就像下面这张图一样。
Metrics下列举了基本的性能指标,并且给出页面加载时间的概览。
First meaningful paint
——这代表用户看到初始内容所需的时间。请尽量让它的值小于1秒。 更多资料
First interactive
——这代表可交互元素从展示到响应所需的时间。
Perceptual Speed Index
——这是页面展示可见部分所需时间的平均值。它以毫秒为单位并且取决于窗口的大小。应该尽量让它减少到1250毫秒以内。 更多资料
Estimated Input Latency
——这是网页响应用户输入所需的毫秒数。
Opportunities
——这一部分包含更多的性能细节,将图片、CSS和响应时间的信息都聚合起来了。下面我会逐个讲解并且给出改良策略。
下载CSS文件会阻塞浏览器的渲染过程。也就是说,浏览器会等到CSS文件下载完后才开始渲染内容。比如说你使用了bootstrap,但在项目才启动的时候,你并不需要加载整个组件库来美化你的页面。对此,最简单的处理方法就是只加载必要的CSS文件。
接着,你希望针对不同的屏幕尺寸进行优化。为了减少加载的CSS数量,你可以使用选择性加载的方式,只加载当前屏幕需要的CSS文件。就像下面的代码:
<link href="other.css" rel="stylesheet" media="(min-width: 40em)"> <link href="print.css" rel="stylesheet" media="print">
如果这还没有完全解决你的问题,你可以试试Keith Clark想出来的方法,它可以让你在不阻塞页面渲染的情况下加载CSS文件。这个技巧使用了一个媒体查询为无效值的 link
元素。当媒体查询的计算结果为false时,浏览器仍然会下载样式表,但是不会延迟页面的渲染。你可以把必需的CSS文件分离出来然后再下载它们。 更多资料
减少请求数的重要性不言而喻,但我们仍然要经常提醒自己,不要忘记它。为了减少服务器响应次数,你可以考虑使用CDN存放部分资源文件。还可以使用HTTP2协议、删除不必要的请求或是渲染页面后再懒加载资源等等。
这三个部分都属于图片优化这一类。你可以在 Network
标签中通过筛选 IMG
来获取实际加载了哪些图片以及它们的体积大小。现在只看 Size
和 Time
这两列的数据,看看你是否满意这样的结果。目前还没有普适的标准规定每个文件应该有多大,这完全依赖于客户端设备种类、客户群体和其他你能想到的所有因素。
关于图片优化我还想再补充几点,因为这个问题在Audit的结果报告中会多次出现。
图片分为两类:位图和矢量图。一个位图由像素构成,往往被用来展示图片和复制的动画。比如jpg、jpeg和gif格式。
矢量图由图形组成,被用来展示logo和图标。因为它们在缩放时也能有优异的表现。比如svg。
SVG本身体积已经很小了,但是你还可以通过压缩让它们更小:
由于位图的体积较大,所以要用的优化技巧会多一些。下面是一些让位图保持较大尺寸但又有较小体积的黑科技。
在优化前请先准备好不同版本的图片。我想你不希望在普通手机上展示适用于retina屏幕的图片吧?先准备个三四种版本。手机版、平板、桌面版和retina版。它们的尺寸取决于你的目标设备。如果你不清楚目标设备属于这四种中的哪一个,可以参考 这个链接 。
图片都准备好了吗?img标签的src属性能够帮助我们决定什么时候加载图片。
<img src="ing.jpg" srcset="img.jpg, img2x.jpg 2x" alt="img">
设置 src
是防止浏览器不支持 srcset
属性,而 srcset
是为了那些支持该属性的浏览器。 img2x.jpg
是为了适配 dpr = 2
的retina屏幕。
<img src="img.jpg" srcset="img1024.jpg 1024w, img2048.jpg 2048w" alt="img">
设置 src
是防止浏览器不支持 srcset
属性,而 srcset
是为了那些支持该属性的浏览器。 img1024
是为了适配宽度为1024像素的屏幕。
上面引用的是MDN的 两个例子 。
你也可以使用媒体查询,比如说根据平板或手机使用不同的样式。这种方法最好与CSS预处理配合使用。
作为srcset属性的替代品,媒体查询的规则是写在CSS样式中,而不是写在HTML文件里。在单纯的CSS文件里,这种方法往往事倍功半。但如果你使用CSS预处理提供的mixin和变量的话,效率就会非常高了。当然,是使用srcset还是媒体查询都随你意。
@desktop: ~"only screen and (min-width: 960px) and (max-width: 1199px)"; @tablet: ~"only screen and (min-width: 720px) and (max-width: 959px)"; @media @desktop { footer { width: 940px; } } @media @tablet { footer { width: 768px; } }
当准备好图片资源并且代码优化后,你需要考虑分发的问题。像Cloudinary这样的工具能够有效地降低响应延时。它们的服务器遍布全球,所以能够快速分发数据。HTTP协议限制用户每次只能向一个服务器并行发送6个请求,而使用CDN的话你能发送的请求数是它的数倍。
有的图片色彩更饱满但体积也更大。如果你的网站还有很高的加载延迟,可以试试blurry image或是懒加载。
懒加载能够让图片按需加载。如果一个画廊有1000张图片,那么这些图片并不需要一开始就被下载好。我们可以先加载前十张图片,然后在用户想要查看时再加载剩下的。
关于懒加载的 第三方库 实在是太多了。
Blurry是现在FaceBook使用的技术。当你在网速较低的情况下点开某人的个人主页,网页中展示的图片会从模糊逐渐变得清晰。 更多资料
Diagnostics是检测结果的最后一项。由于其中有一部分已经在上文中提到了,所以我不打算再逐条讲解。接下来,我会笼统地讲另外一部分。
Google喜欢缓存和serverless应用。缓存策略完全由你决定,反正我是对其兴趣不大。如果你想了解更多关于缓存的事,Google为你准备了一些不错的 教程 。
关键请求链是需要在页面渲染前完成的请求的集合。所以最好尽可能地减少它的数量。
之前我们提到过CSS优化,那么现在再来聊聊网络字体的优化。
在我们的网站中,往往会使用到EOT、TTF、WOFF或WOFF2格式的字体文件。
由于没有统一的标准格式,所以对于每个浏览器我们都需要使用一种不同的字体文件来适配。关于这个问题你可以看看 这篇文章 。在此之前,你可以先问问自己是否真的需要使用网络字体。这个答案也许可以在 这篇文章 中找到。
字体是图形和路径的集合,这个集合帮助我们生成字母和文字。幸运的是,每一个不同的字母都有相似的地方,所以我们可以对它们进行压缩。
由于EOT和TTF格式默认是未压缩的,所以确保你的服务器已经开启GZIP配置。
WOFF是内置了压缩功能的,所以在你的服务器上请使用最优压缩方式。
WOFF2则有预处理机制。 更多资料
如果你的网站语言是英文,那么没必要引入阿拉伯或希腊文。你也可以使用unicode字符集,这样可以让浏览器将大的unicode字体拆分成一个一个子集。 更多资料
由于浏览器在构建DOM时需要使用到字体,因此加载字体文件也会阻塞页面的渲染。
合理地使用字体加载策略能够降低加载的延迟。CSS属性 font-display
就是一种字体加载策略。 更多资料
目前,ES6的模块机制让Webpack和Gulp被广泛使用。当项目中需要使用第三方库时,切记你需要的只是整个库中的一小部分。所以当你不需要 lodash
的全部功能时,你可以只导入需要的函数:
import _ from 'lodash';
——整个lodash库都会被打包
import {map} from 'lodash';
——这也会打包整个lodash模块。你可以使用 lodash-webpack-plugin 或 babel-plugin-lodash 等插件。
import map from 'lodash/map';
——这样只会打包map模块
仔细检查你使用的框架中有哪些原生方法与ES6方法。有时候你并不需要针对每个功能都引入一个不同的库。你可以使用下面链接中的工具检查bundle包是如何生成的。
除了上文提到的Google Devtool,还有其他用来检查性能的工具。
tools.pingdom.com 就是其中之一,它兼具了Audits与Network标签对应的功能。
我还向您推荐PageSpeed Insights,这是一个Chrome的插件。它会告诉你哪些图片需要被优化。
本文的目的是向你展示如何通过减少资源文件体积来轻量化你的网站。而这仅仅是优化性能的第一步罢了。毕竟性能优化这个方向太广了,而且还会随着现代前端的发展而变化。所以你需要持续关注这个领域并且保持竞争力,始终领先他人一步。
查看更多我翻译的Medium文章请访问:
项目地址: https://github.com/WhiteYin/translation
SF专栏: https://segmentfault.com/blog/yin-translation