一、浏览器访问优化
![img_f376238e4acbd2d991ddaa7a5993e7e7.png](https://yqfile.alicdn.com/img_f376238e4acbd2d991ddaa7a5993e7e7.png?x-oss-process=image/resize,w_1400/format,webp)
1.减少http请求
http协议是无状态的用用层协议,意味着每次http请求都需要建立通信链路、进行数据传输,而在服务器端,每个http都需要启动独立的线程去处理。这些通信和服务的开销都很昂贵,减少http请求的数目可有效提供访问性能。
1)合并css、合并javascript、合并图片。将浏览器一次访问需要的js和css合并成一个问价,这样浏览器就只需要一次请求。图片也可以合并,多张图片合并成一张,如果没涨图片都有不同的超链接,可通过css便宜响应鼠标点击操作,构造不同的url.
2)合理设置缓存。很少变化的图片资源可以直接通过HTTP Header中的Expires设置一个很长的过期头,变化不频繁而有可能会变的资源可以使用last-Modifed来做请求验证,尽可能的让资源能够在缓存中待的更久。
2、使用浏览器缓存
1)将更新频率比较低的css、javascript、logo、图标等静态资源文件缓存在浏览器中,避免频繁的http请求,通过设置http 头中cache-contol和expire属性,可设置浏览器缓存,缓存时间可以是数天们甚至是几个月。
2)静态资源文件发生变化的时候,通过生成一个新的js文件并更新HTML文件中的引用来更新hs文件,避免直接更新js文件中的内容。
3)使用浏览器缓存策略的网站在更新静态资源的时候,应该采用逐量更新的方法,比如需要更新10个图标,不宜把10个文件一次全部更新,而是应该一个文件一个文件逐步更新,并有一定的时间间隔,避免用户浏览器大量缓存失效,集中更新缓存,造成服务器负载骤增,网络堵塞的情况。
3、启用压缩
在服务器端对文件进行压缩,在浏览器端对文件进行解压可有效减少通信传输的数据量。如果可以的话,尽可能的将外部的脚本、样式进行合并,多个合并为一个。文本文件的压缩效率可达到80%以上,因此HTML、CSS、javascript文件启用GZip压缩可达到比较好的效果。但是压缩对服务器和浏览器产生一定的压力,在通信宽带良好,而服务器资源不足的情况下要权衡考虑。
4、css Sprites
合并css图片,减少HTTP请求数。
5、LazyLoad Images
这条策略实际上并不一定减少http请求数,但是却能在某些条件下或者页面刚加载时减少http请求数。对于图片而言,在页面刚加载的时候可以只加载一屏的内容,当用户继续向后翻的时候才加载后序的图片。这样一来,假如用户只对第一屏的内容感兴趣的时候,那剩余的图片请求都节省了。
6、css放在页面最顶部,jvascript放在页面最底部
浏览器会在下载完成全部css之后才对整个页面进行渲染,因此最好的做法就是将css放在页面最上面,让浏览器尽快下载css.如果将css放在其他地方,比如body中,则浏览器有可能还未下载和解析到css就已经开始渲染页面了,这就导致页面由无css状态调到css状态,用户体验比较糟糕,可以考虑将css放到HEAD中。js则相反,浏览器在加载js之后立即执行,有可能会堵塞整个页面,造成页面显示缓慢,因此js做好防灾页面下面,但是如果页面解析的时候就要用到js,这时候底部就不合适了。
7、Lazy Load Javascript(只有在需要加载的时候加载,在一般情况下并不加载信息内容)
随着js框架咋流行,越来越多的站点使用起了框架,不过,一个框架往往包括了很多的功能实现,这些功能并不是每一个页面都需要的,如果下载可不需要的脚本则算的上是一种资源浪费,即浪费了宽带也浪费了执行花费的时间。目前的做法大概有两种,一种是为那些流浪特别大的页面专门定制一个mini版框架,另一种是Lazy Load。
8、异步请求callback(就是将一些行为样式提取出来,慢慢加载信息的内容)
在某些页面中可能存在这样一种需求,需要使用script标签来异步的请求数据,类似
![img_d99a9888fb63ae913c15f2935a02f8e4.png](https://yqfile.alicdn.com/img_d99a9888fb63ae913c15f2935a02f8e4.png?x-oss-process=image/resize,w_1400/format,webp)
像以上这种方式直接页面上写<script>对页面的性能也是有影响的,即增加了页面首次加载的负担,推迟了DOMLoaded和window.onload事件的触发机制。如果时效性允许的话,可以考虑在DOMLoaded事件触发的时候加载,或者使用setTimeout方式来灵活的控制加载机制。
9、减少cookie的传输
一方面,cookie包含在每次请求和响应中,太大的cookie会严重影响数据传输,因此那些数据需要写入cookie需要慎重考虑,尽量减少cookie中传输的数据量。另一方面,对于某些静态资源的访问,如css\script等,发送cookie没有意义,可以考虑静态资源使用独立的域名访问,避免请求静态资源的时候发送cookie,减少cookie的传输次数。
10、js代码优化
(1)DOM
a.HTML Collection (HTML收集器,返回的是一个数组内容信息)
在脚本中document.images,docuement.forms、getElementByTagName()返回的都是HTML Collection类型的几何,在平时使用的时候大多将它作为数组来使用,因为它有length属性,也可以使用索引访问每一个元素。不过在访问性能上则比数组要差好多,原因是这个集合并不是一个静态结果,它表示的仅仅是一个特定的查询,每次访问该集合都会重新执行这个查询从而更新查询结果,所谓的‘访问集合’包括读取集合的length属性,访问集合中的元素。
因此当你需要遍历HTML Collection的时候,尽量将他转换成数组再访问,以提高性能,即使不转换为数组,也请尽可能少的访问它。例如唉遍历的时候可以将length属性、成员保存到局部变量后使用局部变量
b、回流和重绘
除了上面一点以外,DOM操作还需要考虑浏览器的重绘和回流,因为这些都是需要消耗资源的。
(2)慎用 with
with(obj){p:1};
代码块的行为实际上是修改了代码块中的执行环境 ,将obj放在了其作用域链的最前端,在 with代码块中访问非局部变量是都是先从 obj上开始查找,如果没有再依次按作用域链向上查找,因此使用 with相当于增加了作用域链长度。而每次查找作用域链都是要消耗时间的,过长的作用域链会导致查找性能下降。
因此,除非你能肯定在 with代码中只访问 obj中的属性,否则慎用 with,替代的可以使用局部变量缓存需要访问的属性。
(3). 避免使用 eval和 Function
每次 eval
或Function 构造函数作用于字符串表示的源代码时,脚本引擎都需要将源代码转换成可执行代码。这是很消耗资源的操作 —— 通常比简单的函数调用慢 100倍以上。
eval 函数效率特别低,由于事先无法知晓传给 eval 的字符串中的内容,eval在其上下文中解释要处理的代码,也就是说编译器无法优化上下文,因此只能有浏览器在运行时解释代码。这对性能影响很大。
Function 构造函数比 eval略好,因为使用此代码不会影响周围代码 ;但其速度仍很慢。
此外,使用 eval和 Function也不利于Javascript 压缩工具执行压缩。
(4). 减少作用域链查找
前文谈到了作用域链查找问题,这一点在循环中是尤其需要注意的问题。如果在循环中需要访问非本作用域下的变量时请在遍历之前用局部变量缓存该变量,并在遍历结束后再重写那个变量,这一点对全局变量尤其重要,因为全局变量处于作用域链的最顶端,访问时的查找次数是最多的。
低效率的写法:
![img_41dc41bade443ba2fae3689f36da81f8.png](https://yqfile.alicdn.com/img_41dc41bade443ba2fae3689f36da81f8.png?x-oss-process=image/resize,w_1400/format,webp)
此外,要减少作用域链查找还应该减少闭包的使用。
(5). 数据访问
Javascript中的数据访问包括直接量 (字符串、正则表达式 )、变量、对象属性以及数组,其中对直接量和局部变量的访问是最快的,对对象属性以及数组的访问需要更大的开销。当出现以下情况时,建议将数据放入局部变量:
a. 对任何对象属性的访问超过 1次
b. 对任何数组成员的访问次数超过 1次
另外,还应当尽可能的减少对对象以及数组深度查找。
(6). 字符串拼接
在 Javascript中使用”+”号来拼接字符串效率是比较低的,因为每次运行都会开辟新的内存并生成新的字符串变量,然后将拼接结果赋值给新变量。与之相比更为高效的做法是使用数组的 join方法,即将需要拼接的字符串放在数组中最后调用其 join方法得到结果。不过由于使用数组也有一定的开销,因此当需要拼接的字符串较多的时候可以考虑用此方法。
10、CSS选择符优化
在大多数人的观念中,都觉得浏览器对 CSS选择符的解析式从左往右进行的,例如
#toc A { color: #444; }这样一个选择符,如果是从右往左解析则效率会很高,因为第一个 ID选择基本上就把查找的范围限定了,但实际上浏览器对选择符的解析是从右往左进行的。如上面的选择符,浏览器必须遍历查找每一个 A标签的祖先节点,效率并不像之前想象的那样高。根据浏览器的这一行为特点,在写选择符的时候需要注意很多事项。
11、CDN加速
cdn(contentdistribute network,内容分发网络)的本质仍然是一个缓存,而且将数据缓存在距离用户比较近的地方,使用户以最快的速度获取数据,即所谓网络第一跳,如下图:
![img_a6a8a62c9687307444b24538efaaa37b.png](https://yqfile.alicdn.com/img_a6a8a62c9687307444b24538efaaa37b.png?x-oss-process=image/resize,w_1400/format,webp)
由于CDN部署在网络运营商的机房,这些运营商有事终端用户的网络服务提供商,因此用户请求路由的第一跳就达到了CDN服务器,当cdn中存在浏览器请求资源的时候,从cnd直接返回给浏览器,最短路径返回响应,加快用户访问速度,减少数据中心负载压力。
CD缓存的一半是静态资源,如图片、文件、css、script脚本、静态网页等、但是这些文件访问频率很高,将其缓存在CND可极大的改善网页的打开速度。
2、反向代理
传统代理服务器位于浏览器一侧,代理浏览器将http请求发送到互联网上,而反向代理服务器位于网站机房一侧,代理网站web服务器接收http请求,如下图如示:
![img_b1b0be3071f7ba65a4957881b80684be.png](https://yqfile.alicdn.com/img_b1b0be3071f7ba65a4957881b80684be.png?x-oss-process=image/resize,w_1400/format,webp)
论坛网站、把热门词条、帖子、博客缓存在反向代理服务器上加速用户访问速度,当这些内容有变化的时候,通过内部通知机制通知反向代理缓存失效,反向代理会重新加载最新的动态内容再次缓存起来。
此外,反向代理也可以实现负载均衡的功能,而通过负载均衡构建的应用集群可以提高系统总体处理能力,进而改善网站高并发情况下的性能。