距上次写博客已经有三个多月的时间了,三四月份一直在忙着找实习,期间还在和同学一起合作项目,五六月份时间基本都花在了项目上,本来就很懒的我,也就懒得写博客了。现在项目总算是要上线了,还是想继续把自己的博客维护下去。最近几篇文章,准备分享找实习和项目相关的,也希望大家多多支持我和同学一起合作的项目,也算是一个创业项目哈。
找实习期间还是面试了很多家公司的,基本大型的互联网公司都有面试过,有一个问题是每次面试官都会问到的,那就是前端的性能优化,所以就总结一下,以备9月份的校招。这些规则呢主要是来自《高性能网站建设指南》这本书,然后雅虎军规加以补充。
减少http请求
学过计算机网络的同学应该都知道,http请求需要进行三次握手,这是很费时间的。通过查看流量也可以发现,大部分的时间都花在了为html文档所引用的所有组件进行的http请求上。因此减少http请求可以提高网站性能。
图片地图
这个我实际用的比较少,就是在一个图片上关联多个url。
CSS Sprites
中文叫雪碧图,将多个图片合并到一个单独的图片中。如果用作背景图片,可以根据background-position来定位背景,这样需要很多张背景图片现在就只需要一张了。也就是本来需要发送多次http请求来请求图片现在只需要发送一次就可以了。
内联图片
通过编码的字符串将图片内嵌到网页文本中。通过使用data: URL模式可以在web页面中包含图片但无需额外的http请求。
合并脚本和样式表
将多个js脚本文件打包成一个文件,将多个css样式表打包成一个样式表。如果分成多个小文件,每个文件都会导致一个额外的http请求。
使用内容发布网络(CDN)
内容发布网络是一组分布在多个不同地理位置的web服务器,用于更加有效地向用户发布内容。在优化性能时,向特定用户发布内容的服务器的选择基于对网络可用度的测量。例如,CDN可能选择网络阶数最小的服务器,或者具有最短响应时间的服务器。这样就能减短网络请求的时间。
添加Expires头
添加Expires头可以最大化地利用浏览器的缓存能力来改善页面的性能。通过使用一个长久的Expires头,使组件被缓存,可以在后续的页面浏览中避免不必要的http请求。
web服务器使用Expires头来告诉web客户端它可以使用一个组件的当前副本,直到指定时间为止。
Cache-Control
Expires头有一定的限制,就是要求服务器和客户端的时钟严格同步,另外,过期日期需要经常检查。HTTP 1.1引入了Cache-Control头来克服Expires头的限制。Cache-Control可以重写Expires头。
压缩组件
压缩组件可以减小http响应的大小,进而减少响应时间。如果http请求产生的响应包很小,传输时间就会减少。
将样式表放在顶部
将样式表放在文档底部会导致在浏览器中阻止内容逐步呈现,将样式表放在顶部会显得加载速度更快,这样可以是浏览器逐步呈现已经下载的网页内容。对于内容比较多的网页尤其重要,用户不用一直等待一个白屏的页面,而是可以先看已经下载的内容。
将脚本放在底部
在使用样式表时,页面逐步呈现会被阻止,直到所有的样式表下载完成。将样式表移到head中,就能首先下载样式表而不会阻止页面呈现。使用脚本时,所有位于脚本以下的内容,逐步呈现都会被阻塞,将脚本放在页面越靠下的位置,意味着越多的内容能够逐步地呈现。
避免CSS表达式
css表达式的问题在于对其进行求值的频率比我们期望的要高。不只是在页面呈现和大小改变时求值,当页面滚动、甚至用户鼠标在页面上移过时都要求值。
使用外部JavaScript和CSS
纯粹而言,内联的js和css可以产生比外部文件更快的响应速度,因为外部文件需要承担多个http请求带来的开销。尽管如此,现实中还是使用外部文件会产生较快的页面,因为外部文件有机会被浏览器缓存起来。html文档通常不会配置为可以缓存的。
减少DNS查找
Internet是通过ip地址来查找服务器的,由于IP地址很难记忆,通常使用url代替,但是当浏览器发送http请求时还是需要ip地址,DNS就是用来将url映射到ip地址上的。DNS查找当然也是有开销的,通常要花费20-120毫秒。在DNS查找完成之前,浏览器不能从主机名那下载到任何内容。
DNS缓存
DNS查找可以被缓存起来以提高查找性能,通常浏览器和用户主机都会进行DNS缓存。
减少DNS查找
DNS查找的数量与页面中唯一主机名的数量相等,包括页面url、图片、脚本文件、样式表、Flash对象等的主机名。减少唯一主机名的数量就可以减少DNS查找的数量。
精简JavaScript
精简,就是从代码中移除不必要的字符以减小其大小,进而改善页面加载时间。同样,css文件也可以进行精简。压缩同时也可以减小所需要请求文件的大小,进而加快文件的请求。
避免重定向
重定向是将用户从一个url重新路由到另一个url,重定向会使页面加载变慢。
移除重复脚本
在一个页面中两次包含同样的一个js文件会损伤性能。一个大型的网站可能是多人协作或者多团队协作的,这样脚本被重复添加是很可能发生的事情。重复的脚本会增加不必要的http请求和浪费执行js所用的时间,这样会损伤页面性能,所以需要避免使用同样的脚本。
配置ETag
当网站被宿主在多于一台服务器上时,ETag头可能会阻碍缓存。当浏览器从一台服务器上获取原始组件,之后,又向另外一台不同的服务器发起条件GET请求时,ETag是不会匹配的,而对于使用服务器集群来处理请求的网站来说,这是很常见的一种情况。所以需要对ETag进行配置,以利用其灵活的验证能力。
雅虎军规补充
延迟加载
延迟加载需要知道网页最初加载需要的最小内容集是什么。剩下的内容就可以延迟加载了。
提前加载
与延迟加载目的相反,提前加载的是为了提前加载接下来网页中要访问的资源。
减少DOM元素数量
网页中元素过多对网页的加载和脚本的执行都是沉重的负担,500个元素和5000个元素在加载速度上会有很大差别。所以减少DOM元素数量是十分有必要的。
减少DOM操作
通过js访问DOM元素没有我们想象中快,元素多的网页尤其慢,利用js对DOM的访问时要注意:
- 缓存已经访问过的元素
- Offline更新节点然后再加回DOM Tree
- 避免通过Javascript修复layout
根据域名划分内容
浏览器一般对同一个域的下载链接数有所限制,按照域名划分下载内容可以增大浏览器并行下载数量,但是也不能盲目增加域名,这样会增加DNS查找的负担。
减少iframe负担
iframe会阻止页面的加载,而且即使iframe内容为空也会消耗时间,所以尽量避免使用iframe。
使用Ajax GET请求
浏览器在实现XMLHttpRequest POST的时候会分成两步,先发送header,然后再发送数据。而GET却可以用一个TCP报文完成请求。另外GET从语义上来讲是去服务器取数据,而POST则是向服务器发送数据,所以我们使用Ajax请求数据的时候尽量通过GET来完成。
避免空的图片src
空的图片src仍然会使浏览器发送请求到服务器,这样完全是不必要的浪费。
用代替@import
@import相当于将css放在网页内容底部。