对于前端的性能优化,主要有分为加载优化和性能优化。在Google官方文档中,给出了性能优化有哪些好处。
前端优化的最终目的都是提升用户体验,改善页面性能。
另外,对于移动端和PC端的优化则有不同之处。这里我们主要介绍PC端的优化。
雅虎23条军规
http://yslow.org/
在前端技术早期,雅虎提出了优化技巧,虽然部分已经过时,但是仍然具有参考意义。
加载优化(网络加载类)
1. 减少HTTP资源请求次数。
目的:HTTP请求次数的减少也就意味着请求时间和资源的减少,可以缩短首次访问的等待时间。
实现:通过构建工具合并雪碧图、CSS/JS代码等。
2. 减小HTTP请求大小。
目的: 和前面一样,都是为了减少请求等待时间和资源大小。
实现:减少没必要的图片、代码加载,对文件进行压缩优化,比如gzip压缩,都可以用来减小文件的大小,缩短网络传输等待延迟。
3. 将CSS或JS放到外部文件中,避免使用<style>
或<script>
标签直接引入。
目的:有效的利用浏览器的静态资源缓存机制。
4. inline CSS/JS。适当的将CSS或JS代码直接写入HTML中。
目的:减少请求。
看到这里,3和4或许有些矛盾。但是其实是合理的。我们需要根据具体场景需求来决定哪种操作。将CSS或JS放到外部文件中,是因为这样可以有效的利用浏览器的静态资源缓存。而使用inline CSS/JS操作是为了减少请求,对于第4种优化优化操作,一般都是将一些基础的、简单的CSS/JS代码直接写入HTML中。
5. 避免页面中空的href和src。
在页面中,一些如<img>
、<link>
、<script>
、<iframe>
等标签的src
或者href
属性为空的时候,浏览器在渲染的时候仍然会进行加载,直至加载失败。这种也是资源的浪费,并且会阻塞其他资源的下载进城。
6. 为HTML指定Cache-Control或Expires
Cache-Control
这里我们利用该属性,同样也是合理的利用浏览器的缓存机制。
7. 合理设置Etag和Last-Modified
目的:优化、利用浏览器缓存机制,减少web资源下载的带宽消耗兵降低服务器负载。
8. 减少页面重定向
目的:减少页面重定向产生的等待时间。一次重定向大约需要600毫秒的时间开销。
9. 增加下载并行数
目的:增加浏览器加载资源时的并行下载数量,缩短页面加载的时间。
实现:使用静态资源分域存放。
浏览器在同一时刻同一个域名下发起的请求是有限的,所以我们可以利用这一点来优化请求,设置多个子域来存放不同的静态资源,当然,也会出现并行次数不足,导致产生一个空闲时间,这就是资源浪费。所以我们要合理的利用浏览器的并行限制。
10. 利用静态资源CDN来存储文件
目的:减小资源请求的所消耗的时间。
CDN的介绍网上很多,这里简单说一下,之所以推荐使用CDN,是因为:1.CDN请求不会携带cookie;2. CDN可以选择最优、最近的请求地址去请求资源,并且可以减少主服务器的压力。
11. 使用CDN Combo下载传输内容
将多个文件打包成一个文件的形式来返回,减少了HTTP请求次数。
12. 使用可缓存的AJAX
在jQuery的$ajax
方法中有一个cache
属性,我们可以通过设置为true
来实现数据的缓存。所以,我们对于返回的内容相同的请求,没有必要每次都去从服务器拉去,只需要在第一次获取到数据的后将其缓存起来,从而加快响应速度并减轻服务器压力。
13. 使用GET来发送AJAX
之所以尽量使用GET而不是用POST,是因为POST在发送之前会先发送一个请求头,来确认是否可以向服务器发送数据,然后在发送正文数据。在跨域的时候尤为明显,会先发送一个OPTIONS请求。而使用GET则只需要发送头部,很明显,效率更好。在向服务器进行读取操作的时候优先考虑。
当然,并不是说所有的情况下都是用GET,具体需要根据我们的业务需求。
14. 减少Cookie的大小并且进行Cookie隔离
熟悉HTTP请求的同学应该清楚,每次发送请求的时候,HTTP头都会携带一大串的Cookie信息,这无疑增加了请求所需要的时间,所以我们尽量减少cookie。比如可以使用localStorage。另外,可以将cookie存放在不同的域名下,因为cookie是不能跨域的,这也就是所说的cookie隔离。
15. 优化favicon.ico图标
favicon.icon图标基本上是一成不变的,所以我们直接对其进行缩小并缓存起来,避免重复请求加载。
16. 使用异步加载Javascript资源
加载JS资源会阻塞文档解析,而异步加载则可以优先渲染页面,然后在加载脚本执行。比如JS可以对script
标签设置defer
或async
属性来实现。
17. 消除CSS/JS资源阻塞
这里的目的和前面的使用异步加载JavaScript资源一个道理,都是为了放置阻塞。这里我们可以对资源进行合理的拆分或延后加载(如前面提到的defer
)。保证关键路径的资源加载。
18. 避免使用CSS import 引用加载CSS
CSS中的@import可以从另一个样式文件中引入样式,但是我们要根据需求,合理的去利用。因为使用 @import会增加CSS资源加载的关键路径的长度,带有@import的CSS样式需要在CSS文件中串行解析到@import时才会加载另外的CSS文件,延后了CSS渲染完成的时间。
20. 预加载技术
在用户空闲时间,提前将下一页数据进行加载。
执行优化(页面渲染类)
1. 把CSS资源应用放置到HTML顶部
这里也是为了让CSS优先下载尽早完成页面渲染。
2. JS资源放置到HTML文件底部
这里也是为了解决加载阻塞的问题,以便更快的渲染页面。
3.减少页面重排重绘
比如避免在HTML中直接缩放图片、减少DOM的操作。
4. 减少DOM元素数量和深度
浏览器解析DOM树是一个开销很大的过程。熟悉AST语法树的应该清楚,如果DOM结构越深、数量越多,其AST结构越复杂,很明显解析的时间相对也就越长。
5. 尽量避免使用<table>、<iframe>等慢元素
浏览器在渲染table的时候是将table的DOM渲染树全部生成,然后一次性的绘制到页面上,所以当表格很长的时候,渲染所产生的资源开销很大,应该尽量避免使用。而iframe
内的资源下载过程会阻塞父页面静态资源的下载与CSS、HTML DOM的解析。
6. 避免运行耗时的JS
这里和前面的异步加载JS一个思路,防止一些加载执行时间过长的JS代码阻塞后面的内容。
7. 避免使用CSS表达式和CSS滤镜
总结
对于前端性能优化,主要分为执行优化和加载优化,对于执行优化。总体思路就是尽量减少页面的重绘和重排,加快页面渲染速度;而对于加载优化,总体思路就是优化HTTP请求中所消耗的时间,避免无效的请求以及资源的浪费。
或许在上面的优化手段中,很多看起来会很矛盾,其实每个手段都有自己要解决的问题。具体选择哪种优化手段、倾向解决哪种问题,需要我们根据实际开发需求来选则。
另外,移动端和PC端的优化有些许差别。因为我们需要考虑到移动端一个较为明显的特点:设备屏幕小、可用的CPU计算资源和网络资源极为有限。因此我们需要对移动端特别的关注,减少没必要的请求,合理利用空闲时间,提前加载,保证首屏渲染速度等。