这是我参与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)
上面讲到的是文件直接合并,但图片文件显然不能像字符串那样直接加起来,于是前端程序员发明了精灵图(也译为雪碧图),原理很简单:
- 用制图软件把十张图片依次拼合成一张大图。
- 然后用 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 社区提供了很多插件来实现这些功能。
但这种方式也有弊端:
- 一旦将资源内联了,就没有了并行下载这些资源的可能性了。所以实践中,我们只会内联体积较小的文件(比如小于 4Kb),大文件尽量并行下载。
- 这些内联文件无法单独地被浏览器缓存,只要有任何一个字符变化了,之前的缓存就失效了,新的文件需要被整个重新下载。 另外,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 可以精简图片文件。
最后说一句
如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下,您的支持是我坚持写作最大的动力,多谢支持。