web性能优化技巧篇之 HTTP优化

475 阅读3分钟

这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战

合并资源(HTTP Concat)

上文讲到,可以通过 Connection: keep-alive 来利用一个 TCP 连接下载多个文件。 2012年左右,淘宝的工程师想到了一种把多个文件打包为一个文件的办法。 假设目前页面中用到的 CSS 文件有 1.css、2.css、3.css,对应的代码为:

<link href="http://cdn.taobao.com/1.css" rel="stylesheet">
<link href="http://cdn.taobao.com/2.css" rel="stylesheet">
<link href="http://cdn.taobao.com/3.css" rel="stylesheet">

淘宝的前端想到的办法是把代码写成:

<link href="http://cdn.taobao.com/??1.css,2.css,3.css" rel="stylesheet">

但目前这种优化方式已经过时了,原因是现代前端工具(如 Webpack)已经提供了把多个文件打包成一个文件的能力,没有必要改造 Nginx。

合并图片(CSS Sprites)

上面讲到的是文件直接合并,但图片文件显然不能像字符串那样直接加起来,于是前端程序员发明了精灵图(也译为雪碧图),原理很简单:

  1. 用制图软件把十张图片依次拼合成一张大图。
  2. 然后用 CSS background-position 来定位图片以在不同的 div 里显示不同的部分。

一些 grunt/gulp/webpack 插件可以自动完成这些工作。合并图片的好处显然也是减少 HTTP 的请求数。

内联资源(Inline Resource)

在 HTTP/2.0 还没普及的公司,程序员为了让资源加载更快,经常会把资源内嵌在 HTML 里,以大大减少 HTTP 请求的数量,以此降低 TCP 连接的数量。比如:

  • <link href="style.css" rel="stylesheet"> 改写为 <style>内嵌style.css的文件内容</style>
  • <script src="main.js"></script> 改写为 <script>内嵌main.js的文件内容<script>
  • <img src="1.png"> 改写为 <img src="data:image/png;base64,iVBORw0...%3D">

自动化脚本的实现思路也很简单:在打包阶段扫描 HTML,一旦发现可内联的资源,就去读取对应的文件内容,替换原来的标签。其中图片文件可以内联为 base64 字符串。Webpack 社区提供了很多插件来实现这些功能。

但这种方式也有弊端:

  1. 一旦将资源内联了,就没有了并行下载这些资源的可能性了。所以实践中,我们只会内联体积较小的文件(比如小于 4Kb),大文件尽量并行下载。
  2. 这些内联文件无法单独地被浏览器缓存,只要有任何一个字符变化了,之前的缓存就失效了,新的文件需要被整个重新下载。 另外,Webpack 在做 code split 的时候,会尽量让每个文件大于 20Kb,防止小文件过多

开启压缩(Gzip)

如果我们把 HTTP 响应的消息体先压缩(字节数可以减少 30% 到 60% 左右),浏览器收到之后再解压缩,那么传输速率又会提高不少。

具体做法也很简单,只需要在 Nginx 配置中添加 gzip on 即可。

代码最小化(Minify)

JS 中 var userName = 'frank'; console.log(userName)var a = 'frank'; console.log(a) 实际上是等价的,于是有人想出了用更简短的代码来代替原有代码的办法。Webpack 在生产环境默认开启了此功能,所以不需要额外配置。

但还有更厉害的代码精简技巧,比如:

  • HTMLMinifier 可以精简 HTML。
  • cssnano 可以精简 CSS 代码。
  • TreeShaking 技术可以进一步精简 JS 代码。
  • svgo 可以精简 SVG 文件。
  • imagemin 可以精简图片文件。

最后说一句

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下,您的支持是我坚持写作最大的动力,多谢支持。