一般说来Web前端指网站业务逻辑之前的部分,包括浏览器加载、网站视图模型、图片服务、CDN服务等,主要优化手段有优化浏览器访问、使用反向代理、CDN加速等。
在浏览器(客户端)和服务器发生通信时,就已经消耗了大量的时间,尤其是在网络情况比较糟糕的时候,这个问题尤其的突出。
一个正常HTTP请求的流程简述:如在浏览器中输入”www.xxxxxx.com”并按下回车,浏览器再与这个URL指向的服务器建立连接,然后浏览器才能向服务器发送请求信息,服务器在接受到请求的信息后再返回相应的信息,浏览器接收到来自服务器的应答信息后,对这些数据解释执行。
HTTP协议是无状态的应用层协议,意味着每次HTTP请求都需要建立通信链路、进行数据传输,当我们请求的网页文件中有很多图片、CSS、JS甚至音乐等信息时,将会频繁的与服务器建立连接并释放连接,这必定会造成资源的浪费 ,而在服务端,每个HTTP都需要启动独立的线程去处理,这些通信和服务的开销都很昂贵,每个HTTP请求都会对服务器和浏览器产生性能负担。
网速相同的条件下,下载一个100KB的图片比下载两个50KB的图片要快。
减少HTTP的主要手段是合并CSS、合并JavaScript、合并图片。将浏览器一次访问需要的JavaScript、CSS合并成一个文件,这样浏览器只需要一次请求。图片也可以合成,多张图片合并成一张,如果每张图片都有不同的超链接,可通过CSS偏移响应鼠标点击操作,构造不同的URL。
对一个网站而言,CSS、JavaScript、Logo、图标这些静态资源文件更新的频率都比较低,而这些文件又几乎是每次HTTP请求都需要的,如果将这些文件缓存在浏览器中,可以极好地改善性能。通过设置HTTP头中的Cache-Control和Expires属性,可设定浏览器缓存,缓存时间可以是数天,甚至是数月。
在某些时候,静态资源文件变化需要及时应用到客户端浏览器,这种情况,可以通过改变文件名实现 ,即更新JavaScript文件并不是更新JavaScript文件内容,而是生成现代战争新的JS文件并更新HTML文件中的引用。
使用浏览器缓存策略的网站在更新静态资源时,应采用分批次更新的方法,比如需要更新10个图标文件,不宜把10个文件一次全部更新,而应该一个文件一个文件逐步更新,并有一定的间隔时间,以免用户浏览器突然大量缓存失效,集中更新缓存,造成服务器负载骤增,网络堵塞的情况。
在服务器端对文件进行压缩,在浏览器对文件解压缩,可有效减少通信传输的数据量。文本文件的压缩率可达80%以上,因此HTML、CSS、JavaScript文件启用GZip压缩可达到较好的效果。但是压缩对服务器和浏览器产生一定的压力,在通信带宽良好,而服务器资源不足的情况下要权衡考虑。
浏览器会在下载完全部CSS之后才对整个页面进行渲染,因此最好的做法是将CSS放在页面最上面,让浏览器尽快下载CSS,HTML规范清楚指出CSS要放包含在页面的区域内。JavaScript则相反,浏览器在加载JavaScript后立即执行,有可能会阻塞整个页面,造成页面显示缓慢,因此JavaScript最好放在页面最下面,但如果页面解析时就需要用到JavaScript,这里放在底部就不合适了。
JavaScript是浏览器中的霸主,为什么这么说,因为在浏览器在执行JavaScript代码时,不能同时做其它事情,即
建议把JavaScript代码放到标签以前,这样既能有效的防止JavaScript的阻塞,又能使得页面的HTML结构能更快的释放。
有一条非常重要的准则一直没有提到,就是CSS和JavaScript的压缩,直接减少下载的文件体积。我个人经常使用的方式是使用 YUI Compressor,它的特点是:移除注释;移除额外的空格;细微优化;标识符替换。
YUI Compressor是java程序,如果你对java很熟悉的话可快速的上手使用yuicompressor.jar;如果你对java很陌生也没关系,一样可以使用YUI Compressor。
以我自己的yuicompressor-2.4.2.jar为例:
1.压缩JS
java -jar yuicompressor-2.4.2.jar api.js > api.min.js
1
2.压缩CSS
java -jar yuicompressor-2.4.2.jar style.css > style.min.css
1
对DOM操作的代价是高昂的,这在网页应用中的通常是一个性能瓶颈,天生就慢。在《高性能JavaScript》中这么比喻:“把DOM看成一个岛屿,把JavaScript(ECMAScript)看成另一个岛屿,两者之间以一座收费桥连接”。所以每次访问DOM都会教一个过桥费,而访问的次数越多,交的费用也就越多。所以一般建议尽量减少过桥次数。
修改和访问DOM元素会造成页面的重绘和重排,循环对DOM操作更是罪恶的行为。 所以请合理的使用JavaScript变量储存内容,考虑大量DOM元素中循环的性能开销,在循环结束时一次性写入。减少对DOM元素的查询和修改,查询时可将其赋值给局部变量。
Repaint 和 Reflow 也就是重绘和重排,Repaint(重绘)就是在一个元素的外观被改变,但没有改变布局(宽高)的情况下发生,如改变visibility、outline、背景色等等。
Reflow(重排)就是DOM的变化影响到了元素的几何属性(宽和高),浏览器会重新计算元素的几何属性,会使渲染树中受到影响的部分失效,浏览器会验证DOM树上的所有其它结点的visibility属性,这也是Reflow低效的原因。如:改变窗囗大小、改变文字大小、内容的改变、浏览器窗口变化,style属性的改变等等。如果Reflow的过于频繁,CPU使用率就会噌噌的往上涨,所以前端也就有必要知道 Repaint 和 Reflow的知识。
上面提到通过设置style属性改变结点样式的话,每设置一次都会导致一次reflow,所以最好通过设置class的方式;有动画效果的元素,它的position属性应当设为fixed或absolute,这样不会影响其它元素的布局;如果功能需求上不能设置position为fixed或absolute,那么就权衡速度的平滑性。
总之,因为 Reflow 有时确实不可避免,所以只能尽可能限制Reflow的影响范围。
JSON是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式。同时,JSON是 JavaScript原生格式,这意味着在 JavaScript 中处理 JSON数据不需要任何特殊的 API 或工具包。
与XML序列化相比,JSON序列化后产生的数据一般要比XML序列化后数据体积小,所以在Facebook等知名网站中都采用了JSON作为数据交换方式。
在JSON中,有两种结构:对象和数组。
1. 一个对象以 “ { ” 开始,“ } ” 结束。每个“名称”后跟一个 “ : ” ;“名称/值 对”之间使用 “ , ”(逗号)分隔。 名称用引号括起来;值如果是字符串则必须用引号括起来,数值型则不需要。如:
var obj={"name":"darren","age":24,"location":"beijing"} ;
1
2. 数组是值(value)的有序集合。一个数组以 “ [ ” 开始, “ ] ” 结束。值之间使用 “ , ” (逗号)分隔。如:
var jsonlist=[
{"name":"darren","age":24,"location":"beijing"},
{"name":"weidong.nie","age":24,"location":"hunan"}
];;
1
对这种数组和对象字面量的操作是非常方便且高效的。如果预先知道JSON结构的情况下,使用JSON进行数据传递简直是太美妙了,可以写出很实用美观可读性强的代码。如果你是纯粹的前台开发人员,一定会非常喜欢JSON。
一方面,Cookie包含在每次请求和响应中,太大的Cookie会严重影响数据传输,因此哪些数据需要写入Cookie需要慎重考虑,尽量减少Cookie中传输的数据量。另一方面对于某些静态资源的访问,如CSS、Script等,发送Cookie没有意义,可以考虑静态资源使用独立域名访问,避免请求静态资源时发送Cookie,减少Cookie传输的次数。
因为Cookie是本地的磁盘文件,每次浏览器都会去读取相应的Cookie,所以建议去除不必要的Coockie,使Coockie体积尽量小以减少对用户响应的影响;
使用Cookie跨域操作时注意在适应级别的域名上设置coockie以便使子域名不受其影响。
Cookie是有生命周期的,所以请注意设置合理的过期时间,合理地Expire时间和不要过早去清除coockie,都会改善用户的响应时间。
CDN的全称是Content Delivery Network,即内容分发网络。
CDN本质仍然是一个缓存,而且将数据缓存在离用户最近的地方,使用户以最快的速度获取数据。
由于CDN部署在网络运营商的桐庐,这些运营商又是终端用户的网络服务提供商,因此用户请求路由的第一跳就到达了CDN服务器,当CDN中存在浏览器请求的资源时,从CDN直接返回浏览器,最短路径返回响应,加快用户访问速度,减少数据中心负载压力。 CDN能够缓存的一般是静态资源,如图片、文件(例如视频)、CSS、Script脚本、静态网页等,这些文件访问频率很高(例如NBA总决赛这些的热门视频文件),将其缓存在CDN可极大改善网页的打开速度。
实时性不太好是CDN的缺陷。随着对CDN需求的逐渐升温,这一缺陷将得到改进, 使来自于远程服务器的网络内容网页与副本服务器或缓存器中的网页保持同步。解决方法是在网络内容发生变化时将新的网络内容从服务器端直接传送到缓存器,或者当对网络内容的访问增加时将数据源服务器的网络内容尽可能实时地复制到缓存服务器。
原文链接:https://www.cnblogs.com/cscredis/p/9289634.html