也会因此而感谢你,当然他们可能压根没注意到你的网站速度加快了——这是好事。

在这篇文章里,我会告诉你一些提升网站速度的方法。

我们开始吧。

基准

首先,用你的网站来做示例。

你需要使用 Google 的 Pagespeed Insights 网站测试工具来测试你的网站,它会告诉你,你的网站需要优化移动端还是桌面端。
微信截图_20200220113706.png
Google 基于网页的渲染速度来打分。它会计算你的网站需要多久呈现到用户眼前。用户等待的时间越长,网站的得分就越低。
我对 Google 的 Pagespeed Insights 测试工具的主要不满在于它太慢了。可以说是……难以忍受的慢。

如何解决呢?

Lighthouse

使用 Lighthouse

你可以通过 npm 下载 Lighthouse 到电脑上。它实际上是一个功能更强大的Pagespeed Insights 测试工具(Pagespeed Insights 是基于 Lighthouse 实现的)。

当你在本地使用它时,测试生成的所有信息都可以保存下来。

使用方法如下:

  • 下载

npm install -g lighthouse

此外需要确保已经下载了某些版本的 Google Chrome

  • 接下来你就可以使用它并生成测试结果了:

lighthouse https://www.xxxx.com

--view 会在你的默认浏览器中打开测试结果。以下是我之前使用 Lighthouse 测试的结果:

lighthouse是直接集成到chrome开发者工具中的,位于Audits面板下。

首先,你得下载安装 了chrome浏览器,相信每个做开发的人员都应该拥有chrome浏览器。

其次,在chrome浏览器中打开你需要测试的网站,按f12进入开发者调试模式,点击Audits选项

当然,前提是你有个梯子

测试结果不仅包括性能得分,还包括可访问性、最佳实践和 SEO 建议。它的不足之处是每次只能测试一个页面。我建议你测试内容较多的页面,这样一来,你测得的就是网站中性能最差的一页的结果。当你修复了最差的页面,整个网站的性能也会得到大幅提升。
微信截图_20200220115831.png
微信截图_20200220115840.png
微信截图_20200220120431.png

图一 CPANEL,图二BACKSTAGE,图三JOYNOP.COM(本站)

性能量化

下列举了基本的性能指标,并且给出页面加载时间的概览。

First meaningful paint——这代表用户看到初始内容所需的时间。请尽量让它的值小于1秒。

First interactive——这代表可交互元素从展示到响应所需的时间。

Perceptual Speed Index——这是页面展示可见部分所需时间的平均值。它以毫秒为单位并且取决于窗口的大小。应该尽量让它减少到1250毫秒以内。
Estimated Input Latency——这是网页响应用户输入所需的毫秒数。

Opportunities——这一部分包含更多的性能细节,将图片、CSS和响应时间的信息都聚合起来了。下面我会逐个讲解并且给出改良策略。

Reduce render-blocking stylesheets
下载CSS文件会阻塞浏览器的渲染过程。也就是说,浏览器会等到CSS文件下载完后才开始渲染内容。比如说你使用了bootstrap,但在项目才启动的时候,你并不需要加载整个组件库来美化你的页面。对此,最简单的处理方法就是只加载必要的CSS文件。

接着,你希望针对不同的屏幕尺寸进行优化。为了减少加载的CSS数量,你可以使用选择性加载的方式,只加载当前屏幕需要的CSS文件。就像下面的代码:

<link href="other.css" rel="stylesheet" media="(min-width: 40em)">
<link href="print.css" rel="stylesheet" media="print">

如果这还没有完全解决你的问题, 在不阻塞页面渲染的情况下加载CSS文件。这个技巧使用了一个媒体查询为无效值的link元素。当媒体查询的计算结果为false时,浏览器仍然会下载样式表,但是不会延迟页面的渲染。你可以把必需的CSS文件分离出来然后再下载它们。

Keep server response times low

减少请求数的重要性不言而喻,但我们仍然要经常提醒自己,不要忘记它。为了减少服务器响应次数,你可以考虑使用CDN存放部分资源文件。还可以使用HTTP2协议、删除不必要的请求或是渲染页面后再懒加载资源等等。

Properly size Images, Offscreen images 和 next-gen formats

这三个部分都属于图片优化这一类。你可以在Network标签中通过筛选IMG来获取实际加载了哪些图片以及它们的体积大小。现在只看Size和Time这两列的数据,看看你是否满意这样的结果。目前还没有普适的标准规定每个文件应该有多大,这完全依赖于客户端设备种类、客户群体和其他你能想到的所有因素。
查看加载的图片

关于图片优化我还想再补充几点,因为这个问题在Audit的结果报告中会多次出现。

图片优化

图片分为两类:位图和矢量图。一个位图由像素构成,往往被用来展示图片和复制的动画。比如jpg、jpeg和gif格式。

矢量图由图形组成,被用来展示logo和图标。因为它们在缩放时也能有优异的表现。比如svg。

SVG

SVG本身体积已经很小了,但是你还可以通过压缩让它们更小:

SvgOmg

Svg-optimiser

位图

由于位图的体积较大,所以要用的优化技巧会多一些。下面是一些让位图保持较大尺寸但又有较小体积的黑科技。

事前准备

在优化前请先准备好不同版本的图片。我想你不希望在普通手机上展示适用于retina屏幕的图片吧?先准备个三四种版本。手机版、平板、桌面版。它们的尺寸取决于你的目标设备。如果你不清楚目标设备属于这四种中的哪一个,可以参考这个链接。

Srcset属性

图片都准备好了吗?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;
  }
}

CDN

当准备好图片资源并且代码优化后,你需要考虑分发的问题。像Cloudinary这样的工具能够有效地降低响应延时。它们的服务器遍布全球,所以能够快速分发数据。HTTP协议限制用户每次只能向一个服务器并行发送6个请求,而使用CDN的话你能发送的请求数是它的数倍。

懒加载

有的图片色彩更饱满但体积也更大。如果你的网站还有很高的加载延迟,可以试试blurry image或是懒加载。

懒加载能够让图片按需加载。如果一个画廊有1000张图片,那么这些图片并不需要一开始就被下载好。我们可以先加载前十张图片,然后在用户想要查看时再加载剩下的。

关于懒加载的第三方库实在是太多了。

优化网络字体

之前我们提到过CSS优化,那么现在再来聊聊网络字体的优化。

在我们的网站中,往往会使用到EOT、TTF、WOFF或WOFF2格式的字体文件。

由于没有统一的标准格式,所以对于每个浏览器我们都需要使用一种不同的字体文件来适配。关于这个问题你可以看看这篇文章。在此之前,你可以先问问自己是否真的需要使用网络字体。这个答案也许可以在这篇文章中找到。

字体压缩

字体是图形和路径的集合,这个集合帮助我们生成字母和文字。幸运的是,每一个不同的字母都有相似的地方,所以我们可以对它们进行压缩。

由于EOT和TTF格式默认是未压缩的,所以确保你的服务器已经开启GZIP配置。
WOFF是内置了压缩功能的,所以在你的服务器上请使用最优压缩方式。
WOFF2则有预处理机制。

限制字符集

如果你的网站语言是英文,那么没必要引入阿拉伯或希腊文。你也可以使用unicode字符集,这样可以让浏览器将大的unicode字体拆分成一个一个子集。

字体加载策略

由于浏览器在构建DOM时需要使用到字体,因此加载字体文件也会阻塞页面的渲染。

合理地使用字体加载策略能够降低加载的延迟。CSS属性font-display就是一种字体加载策略。

JavaScript优化

减少引入不必要的依赖

目前,ES6的模块机制让Webpack和Gulp被广泛使用。当项目中需要使用第三方库时,切记你需要的只是整个库中的一小部分。所以当你不需要lodash的全部功能时,你可以只导入需要的函数:

import _ from 'lodash';——整个lodash库都会被打包
import {map} from 'lodash';——这也会打包整个lodash模块。你可以使用lodash-webpack-pluginbabel-plugin-lodash等插件。

import map from 'lodash/map';——这样只会打包map模块

仔细检查你使用的框架中有哪些原生方法与ES6方法。有时候你并不需要针对每个功能都引入一个不同的库。你可以使用下面链接中的工具检查bundle包是如何生成的。

Webpack bundle analyzer