本文为Steve Souders的《High Performance Web Sites》读书笔记,主要介绍14条用于前端优化网站性能的建议。
Rule 1: Make Fewer HTTP Requests(减少HTTP请求)
- Image Maps
在看到这个名词之前,甚至没听说过它。稍微了解了下,知道大概就是可以用一张图片当成地图,然后点击图片上某一点,触发相应的事件。用到的场景可以是电商的服装广告上,比如一张模特图片,点击衣服,跳转衣服链接,点击鞋子,跳转鞋子链接。也可以是导航为图片的情况,点击导航对应的信息,相应执行动作。
使用图片地图可以减少多张图片进行多次HTTP请求。
example for no
example for yes - CSS Sprites
这个比较常用在图片图标情况下。
example for yes - Inline Images
可以使用“data:”内联图片,不用额外再去请求图片。
example for html yes
example for css yes - Combined Scripts and Stylesheets
可以使用一些工具,如webpack/gulp,将脚本合并,样式表合并。虽然两者还可以合并,但不建议这么做。
example for no
example for yes
Rule 2: Use a Content Delivery NetWork(使用内容分发网络)
- CND
先要了解下CND–内容分发网络。它是一组分布在多个不同地理位置的Web服务器,可以更加有效的向用户发布内容。个人感觉最简单的解释就是可以让用户就近请求资源。
Rule 3: Add an Expires Header(添加Expires头)
- Expires
Web服务器使用Expires来告诉客户端该资源在某时间之前是有效的。客户端在服务端没有更新资源的情况下,可以在这段时间内一直使用之前请求到的资源的副本。 - Max-Age & mod_expires
使用Expires有一些限制,比如需要客户端和服务端的时钟需要严格同步,然后还要经常检查过期日期,一旦过期,还得提供一个新的日期。
在HTTP1.1种,引入了Cache-Control。这时我们可以换一种方式,使用Cache-Control的Max-Age替代Expires。它表示资源可以被缓存多长时间,以s为单位。
为了兼容,可以同时指定这两个响应头。HTTP规范规定,如果这两者同时存在,Max-Age将重写Expires。 - Empty Cache vs Primed Cache
如果你的页面中可缓存资源都在缓存中,则缓存是“完整的”。如果你页面中的资源没有放在缓存中,则缓存为“空”。这两者使用场景不一样,使用时,视情况而定。 - More Than Just Images
图片添加Expires很正常,我们也应该给其他不经常变化的资源添加Expires,比如脚本、样式表等。 - Revving FileNames
如果像上面那样给资源添加Expires,那么怎样让其获取更新呢?一般的实现是替换文件名,加一个版本信息后缀。
Rule 4: Gzip Components(压缩组件)
- How Cpmpression Works
Web客户端可以通过HTTP请求中的Accept-Encoding头来标识对压缩的支持。如果Web服务器看到请求中的这个头,就会使用客户端列出来所支持的一种压缩方法来响应。
Web服务器通过响应中的Content-Encoding头来通知Web客户端。gzip是目前最流行和最有效的压缩方法,还有一种较普遍的压缩格式为deflate。支持deflate的浏览器也支持gzip,但支持gzip的浏览器却不一定支持deflate。
Rule 5: Put Stylesheets at the Top(将样式表放在顶部)
- Progressive Rendering
将样式表放在文档底部时,浏览器会延迟显示任何可视化的组件,这带来了很糟糕的用户体验,有时甚至会带来“白屏”现象。一般我们把样式表都放在文档的顶部。 - Flash of Unstyled Content
“白屏”现象源自于浏览器的行为。“FOUC”–“无样式内容的闪烁”,简单说就是当样式加载完成,某组件会突然加载上某个样式,出现闪烁现象。
“白屏”现象是浏览器在尝试修改前端工程师所犯的错误–延迟呈现。 - What’s a Frontend Engineer to do?
如何避免“白屏”和“FOUC”现象呢?
最佳的解决方案是遵循HTML规范,将样式表放在顶部。如果你的样式表不要求呈现页面,可以想办法在文档加载完毕后动态的加载进来,即“加载后下载”。
Rule 6: Put Scripts at the Bottom(将脚本放在底部)
- Parallel Downloads
对响应时间影响最大的是页面中组件的数量。浏览器可并行下载组件数量有限,可能4个,可能8个。修改浏览器设置可能可以增加并行下载数量。但这个取决于你的带宽和CPU速度,过多的并行下载可能反而会降低性能。 - Scripts Block Downloads
在下载脚本时,浏览器会阻塞并行下载。其中一个原因就是为了保证脚本能够按照正确的顺序执行。另一个原因是脚本可能使用document.write来修改页面内容,因此浏览器会等待,以确保页面能够恰当的布局。 - Worst Case: Scripts at the Top
如果将脚本放在页面顶部,页面中的所有东西都位于脚本之后,那么整个页面的呈现和下载都会被阻塞,直至脚本加载完毕。 - Best Case: Scripts at the Bottom
将脚本放在页面的底部是最佳的方案,既不会阻止页面内容的呈现,还可以让页面中的可视化组件尽早下载。 - Putting it in Perspective
如果某个脚本下载等待时间很长,但我们不想等待这么长时间。那么可以使用Defferred(延迟)脚本。DEFER属性表明脚本不包含document.write,浏览器可以继续呈现。
Rule 7: Avoid CSS Expressions(避免CSS表达式)
- Working Around the Problem
如果需要动态改变样式,可以使用事件处理器。
Rule 8: Make JavaScript and CSS External(使用外部JavaScript和CSS)
- Inline
内联快一些。 - Component Reuse
如果你的网站中的每个页面或者多个页面都使用了相同的JavaScript和CSS,使用外部文件可以提高这些组件的重用性,这时,使用外部文件更加具有优势。 - Post-Onload Download
我们希望为主页内联JavaScript和CSS,但又能为所有后续页面查看提供外部文件。这时可以通过在主页加载完成后动态下载外部组件来实现(通过onload事件),这能够将外部文件放到浏览器的缓存中以便用户接下来访问其他页面。12345678910111213141516171819202122<script>function doOnload(){setTimeout(downloadComponents(),1000);}function downloadComponents(){downloadJS('http://xxx/xxx.js');downloadCSS('http://xxx/xxx.css');}function downloadJS(url){var elem = document.createElement('script');elem.src = url;document.body.appendChild(elem);}function downloadCSS(url){var elem = document.createElement('link');elem.rel = 'stylesheet';elem.type = 'text/css';elem.href = url;document.body.appendChild(elem);}window.onload = doOnload;</script>
Rule 9: Reduce DNS lookups(减少DNS查找)
- DNS Caching and TTLs
DNS查找可以被缓存起来以提高性能。
在用户请求一个主机名之后,DNS信息会留在操作系统的DNS缓存中,之后对于该主机名的请求将无需进行过多的DNS查找。
很多浏览器拥有其自己的缓存,和操作系统的缓存相分离。只要浏览器在其缓存中保留了DNS记录,它就不会麻烦操作系统来请求这个记录。
Rule 10: Minify JavaScript(精简JavaScript)
- Minification
精简,是从代码中移除不必要的字符以减少其大小,所有的注释以及不必要的空白字符将被移除。 - Obfuscation
混淆,同精简一样,它也会移除注释和空白,但同时它也会改写代码,它会使用更短的变量和函数名字替换原有内容。 - Gzip and Minification
使用gzip压缩文件,通常可以使文件大小减小70%,压缩比精简更能减小文件的大小。而且,混淆压缩与精简压缩,效率几乎一样。但使用精简可以避免混淆带来的额外风险。 - Minifying CSS
优化CSS,最大的潜在可能是,合并相同的类、移除不使用的类等。目前的解决方案是移除注释和空白,并进行一些直观的优化,比如使用缩写(‘#ccc’代替’#cccccc’)和移除不必要的字符串,如用’0’代替’0px’。
Rule 11: Avoid Redirects(避免重定向)
- Types of Redirects
重定向请求的响应中会包含一个范围在3xx的状态码。’304 Not Modified’并不是真的重定向–它是用来响应条件GET请求,避免下载已经存在于浏览器缓存中的数据。状态码’306’已经被废弃。 - How Redirects Hurt Performance
第一次请求URL时,接收到3xx重定向,然后请求此时的新url,而且可能会多次重定向,此时直到请求到预期想请求的资源已经经过了好几次http请求,影响性能。
Rule 12: Remove Duplicate Scripts(移除重复脚本)
- Duplicate Scripts Hurt Performance
重复脚本损伤性能的方式有两种–不必要的HTTP请求和执行JavaScript所浪费的时间。
Rule 13: Configure ETags(配置ETag)
- What’s an ETag
实体标签,是Web服务器和浏览器用于确认缓存组件的有效性的一种机制,在HTTP1.1中引入。 - Last Modified Date
服务器通过Last-Modified响应头来返回组件的最新修改日期,下一次请求资源时,浏览器会使用If-Modified-Since头将最新修改日期传回到服务器以进行比较。
如果服务器上组件的最新修改日期与浏览器传回的值匹配,会返回一个304响应,而不会传送当前浏览器请求的资源。 - The Problem with ETags
当浏览器从一台服务器上获取了原始组件,之后又向另外一台不同的服务器发起GET请求时,ETag是不会匹配的,这对于使用服务器集群来处理请求的网站来说,是很常见的一种情况。
Rule 14: Make Ajax Cacheable(使Ajax可缓存)
- Optimizing Ajax Requests
当用户发起主动Ajax请求时,用户可能仍须等待,要改善性能,可以优化这些请求。 - Caching Ajax in the Real World
一个例子,Yahoo Mail。当用户启动Yahoo Mail的Ajax版本时,它会下载前三个Email消息的正文,这是一个聪明的主动Ajax请求,用户很有可能单击这些Email消息中的一个或几个,
它们已经被下载到客户端,这样用户无需进行任务Ajax请求就能看到他们的Email消息。
☜☜☜ wechat 『『『 reward 点击扫码打赏 ~~~ ^_^ 』』』alipay ☞☞☞