您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

HTML5性能优化 - 极道先生

2024/12/2 17:58:12发布21次查看
html5性能优化 
        在看完这两章内容之后,我意犹未尽,于是乎从网上搜索关键字“java web高性能”,在ibm社区找到两篇不错的文章,而让人更意外的是我发现那两篇文章的内容跟《高性能html5》前两章高度相似,不知道是谁抄袭谁的,大家可以鉴别下真伪,下面附上地址。
        http://dl2.iteye.com/upload/attachment/0097/9373/b0e69540-e703-3530-81bb-c93de7b850a6.pdf
        http://www.ibm.com/developerworks/cn/java/j-lo-javawebhiperf1/
        http://www.ibm.com/developerworks/cn/java/j-lo-javawebhiperf2/
前面是读后感,下面是我针对最近几天学习到的提高web性能进行了篇幅不小的总结,一来为新人提供帮助,二来自己做一下笔记,加深记忆。
性能之前端篇--减少重绘
        在html页面完成展现之后,动态改变页面元素或调整css样式都会引起浏览器重绘,性能的损耗直接取决于动态改变的范围:如果只是改变一个元素的颜色之类的信息则只会重绘该元素;而如果是增删节点或调整节点位置则会引起其兄弟节点也一并重绘。
        减少重绘并不是说不要重绘,而是要注意重绘范围:①改动的dom元素越深则影响越小,所以尽量深入节点改动;②对某些dom样式有多重变动尽量合并到一起修改。
以改变一个标签的背景色、宽度和颜色为例。
传统的代码
以上会执行3次重绘,而通过css代替javascript多次执行则只进行一次重绘。
css优化的代码
避免脚本阻塞加载
        当浏览器在解析常规的script标签时,它需要等待script下载完毕,再解析执行,而后续的html代码只能等待。css文件引入要放在
头部,因为这是html渲染必备元素。为了避免阻塞加载,应把脚本放到文档的末尾,而css是需要放在头部的! 
......
--避免节点深层级嵌套
        深层级嵌套的节点在初始化构建时往往需要更多的内存占用,并且在遍历节点时也会更慢些,这与浏览器构建dom文档的机制有关。浏览器会把整个html文档的结构存储为dom“树”结构。当文档节点的嵌套层次越深,构建的dom树层次也会越深。
如下代码,完全能够去掉
或其中一个标签。 嵌套

页面缓存
        通常不设置缓存的情况下,每次刷新页面都会重新读取服务器的文件,而如果设置缓存之后,所有文件都可以从本地取得,这样明显极大提高了页面效率。
我们可以通过设置页面头的expires来定义页面过期时间,将过期时间定久一点就达到了“永久”缓存。
meta http-equiv=expires content=sunday 26 october 2099 01:00 gmt />
当然,如果你的项目代码有变更,因为客户端缓存了文件就得不到最新的文件,势必造成显示错误。基于这个问题的解决方案就是给链接文件加一个时间戳,如果时间戳有变化,浏览器会认为是新文件,就会向服务器请求最新文件。 
//如果是jsp,可以用el表达式来取时间戳信息,这样管理更加方便//或者这样的写法更优秀:
压缩合并文件
        所有涉及到请求数据的文件尽量做压缩,比如javascript文件、css文件及图片文件,特别是图片文件,如果没有高清晰要求,完全可以压缩后再使用。
        数量少体积大的文件要比数量多体积小的文件加载速度快,所以有时候可以考虑将多个js文件、多个css文件合并在一起。
除此之外减少html文档大小还可以采取下面几种方法:
①删掉htm文档对执行结果无影响的空格空行和注释
②避免table布局
③使用html5
--html+css3+javascript各司其职
        让三元素各司其职才能做出高性能的网页:html是页面之本也是内容之源,有了它就能跟css和javascript交互;css3可以说是展现大师,而且日渐强大的css能代替javascript做很多动态的事情如渐变、移动等动态效果;javascript是动态数据之王,旧浏览器依靠js来完成动态效果展现,但现在的css也能完成js的工作,所以尽量将工作交给css,这样会获得更好的性能。(这个说得有点大)
--图像合并实现css sprites
        图像合并其实就是把网页中一些背景图片整合到一张图片文件中,再利用css 的“background-image”,“background- repeat”,“background-position”的组合进行背景定位,background-position可以用数字能精确的定位出背景图片的位置。
        一个页面要用到多个图标,完全可以将多个图标合并成一个图,然后只需要发一次图片请求,通过css定位分割图标即可。
--避免使用iframe
        使用iframe并不会增加同域名下的并行下载数,浏览器对同域名的连接总是共享浏览器级别的连接池,在页面加载过程中iframe元素还会阻塞父文档onload事件的触发。并且iframe是html标签中最消耗资源的标签,它的开销比div、script、style等dom高1~2个数量级。
避免onload事件被阻塞,可使用javascript动态的加载iframe元素或动态设置iframe的src属性(但其仅在高级浏览器ie9及以上有效)。
document.getelementbyid(if).setattribute(src,url);


--多域名请求
        一般来说,浏览器对于相同域名的图片,最多用2-4个线程并行下载(不同浏览器的并发下载数是不同的)。而相同域名的其他图片,则要等到其他图片下载完后才会开始下载。
        有时候,图片数据太多,一些公司的解决方法是将图片数据分到多个域名的服务器上,这在一方面是将服务器的请求压力分到多个硬件服务器上,另一方面,是利用了浏览器的特性。(大家可以去新浪、腾讯门户网站查看,这些大型站点同一页面加载的图片可能由多个站点提供)
        注:一个html请求的域名也不要太多(2~3个差不多),多了可能造成不同服务器连接时间差异,反而影响速度。
--避免空链接属性
        如这样的设置方式是非常不可取的,即使链接为空,在旧的浏览器也会以固定步骤发送请求信息。
        另外也不可取,最好的方式是在链接中加一个空的js代码
--使用图像的base64编码
        base64是一串字符串,他可以代表一个图片的所有信息,也就是可以通过(s表示一串base64码)来显示图片,这种方式不需要再向服务器发送请求,完全由浏览器解析成图片。
        目前高级浏览器都支持此功能,但要注意两点:①低版本浏览器(如ie7)不支持;②base64字符串长度随图片的大小及复杂度成正比,base64也像url一样,也有超出长度的情况(在ie8下很常见)。所以要根据情况来使用。
--显式设置图片的宽高
        如果html里的图片没有指定尺寸(宽和高),或者代码描述的尺寸与实际图片的尺寸不符时,浏览器则要在图片下载完成后再“回溯”该图片并重新显示,这会消耗额外时间。
document.getelementbyid(if).setattribute(src,url);


--显式指定文档字符集
        如果浏览器不能获知页面的编码字符集,一般都会在执行脚本和渲染页面前,把字节流缓存,然后再搜索可进行解析的字符集,或以默认的字符集来解析页面代码,这会导致消耗不必要的时间。
document.getelementbyid(if).setattribute(src,url);


--渐进式增强设计
        渐进式增强设计的通俗解释就是:首先写一段满足所有浏览器的基本样式,再在后面针对不同高级浏览器编写更漂亮的样式
        如下代码,所有浏览器都支持background-color: #2067f5;满足了浏览器基本现实需求,而后面的background-image: -webkit-gradient等则为不同高级浏览器使用,只要浏览器识别就能执行这段代码(不识别,css也不会报错只会直接忽略)。
.someclass { width: 100px; height: 100px; background-color: #2067f5; background-image: -webkit-gradient(linear, left top, left bottom, from(#2067f5), to(#154096)); background-image: -webkit-linear-gradient(top, #2067f5, #154096); background-image: -moz-linear-gradient(top, #2067f5, #154096); background-image: -ms-linear-gradient(top, #2067f5, #154096); background-image: -o-linear-gradient(top, #2067f5, #154096); background-image: linear-gradient(to bottom, #2067f5, #154096); }
参考阅读:多浏览器适配测试
--懒加载与预加载
        预加载和懒加载,是一种改善用户体验的策略,它实际上并不能提高程序性能,但是却可以明显改善用户体验或减轻服务器压力。
        预加载表示当前用户在请求到需要的数据之后,页面自动预加载下一次用户可能要看的数据,这样用户下一次操作的时候就立刻呈现,依次类推。
        懒加载表示用户请求什么再显示什么,如果一个请求要响应的时间非常长,就不推荐懒加载。
--flush机制
        当一个页面非常大,内容非常多,可以采用flush的形式分部分返回给页面,这样能告诉用户我正在工作,显示一部分内容比白屏等很长时间要好得多。在java web技术中,实现flush非常简单,只要调用 httpservletresponse.getwriter输出流的flush方法,就可以将已经完成加载的内容写回给客户端。
        这种方式只适用于返回数据特别多、请求时间特别长的情况,常规数据还是用正常的实时全部返回最佳。这种实现方式实际会增加浏览器渲染时间和用户整体等待时间,但从用户体验上会更加优秀。
性能之服务器优化--cdn机制
        所谓的cdn,就是一种内容分发网络,它采用智能路由和流量管理技术,及时发现能够给访问者提供最快响应的加速节点,并将访问者的请求导向到该加速节点,由该加速节点提供内容服务。
        通俗点说,你在成都(浏览器)购买了北京卖家(服务器)的产品,北京卖家通过快递(cdn服务)寄送包裹,从北京到成都可以走路、坐汽车、火车或飞机,而采用cnd的快递会选择飞机直达,因为这种寄送方式最快。
当然使用cdn有两个注意事项:
1、cdn加速服务很贵,如果你觉得你的网站值得加速,可以选择购买;
2、cdn不适合局域性网站,比如你的网站只有某一个片区访问或者局域网访问,因为区域性网络本来就很近,无需cdn加速。
--http协议的合理使用
        浏览器缓存带来的性能提升已经众人皆知了,而很多人却并不知道浏览器的缓存过期时间、缓存删除、什么页面可以缓存等,都可以由我们程序员来控制,只要您熟悉http协议,就可以轻松的控制浏览器。
扩展阅读:深入理解http协议
--动静分离
        所谓的动静分离,就是将web应用程序中静态和动态的内容分别放在不同的web服务器上,有针对性的处理动态和静态内容,从而达到性能的提升。我们知道如果一个html有多个域名请求数据文件会提高
tomcat服务器在处理静态和并发问题上比较弱,所以事先动静分离的方式一般会用apache+tomcat、nginx+tomcat等。
        以apache+tomcat为例,其运行机理是:页面请求首先给apache,然后apache分析请求信息是静态还是动态,静态则本机处理,动态则交给tomcat做处理。
        这其实是负载均衡的雏形,这样的实现不用让开发人员做任何特殊开发,一个交给服务器即可,至于这个文件是从apache还是从tomcat取得,开发人员完全无需关注。
--http持久连接
        持久连接(keep-alive)也叫做长连接,它是一种tcp的连接方式,连接会被浏览器和服务器所缓存,在下次连接同一服务器时,缓存的连接被重新使用。http无状态性表示了它不属于长连接,但http/1.1提供了对长连接的支持(不过这必须依赖浏览器和服务器双方均支持长连接功能才行),最常见的http长连接例子是“断点下载”。
        浏览器在请求的头部添加 connection:keep-alive,以此告诉服务器“我支持长连接,你支持的话就和我建立长连接吧”,而倘若服务器的确支持长连接,那么就在响应头部添加“connection:keep-alive”,从而告诉浏览器“我的确也支持,那我们建立长连接吧”。服务器还可以通过keep-alive:timeout=..., max=...的头部告诉浏览器长连接失效时间。
        配置长连接通常是要服务器支持设置,有测试数据显示,使用长连接和不使用长连接的性能对比,对于tomcat配置的maxkeepaliverequests为50来说,效率竟然提升了将近5倍。
--gzip压缩技术
        http协议支持gzip的压缩格式,当服务器返回的html信息报头中包含content-encoding:gzip,它就告诉浏览器,这个响应的返回数据已经压缩成gzip格式,浏览器获得数据后要进行解压缩操作,一定程度上减轻了服务器传输数据的压力。
        很多服务器已经支持通过配置来自动将html信息压缩成gzip,比如tomcat、又比如很火的nginx。如果无法配置服务器级别的gzip压缩机制,可以改为程序压缩。
// 监视对 gzipcategory 文件夹的请求 @webfilter(urlpatterns = { /gzipcategory/* }) public class gzipfilter implements filter { @override public void dofilter(servletrequest request, servletresponse response, filterchain chain) throws ioexception, servletexception { string parameter = request.getparameter(gzip); // 判断是否包含了 accept-encoding 请求头部 httpservletrequest s = (httpservletrequest)request; string header = s.getheader(accept-encoding); //1.equals(parameter) 只是为了控制,如果传入 gzip=1,才执行压缩,目的是测试用 if (1.equals(parameter) && header != null && header.tolowercase().contains(gzip)) { httpservletresponse resp = (httpservletresponse) response; final bytearrayoutputstream buffer = new bytearrayoutputstream(); httpservletresponsewrapper hsrw = new httpservletresponsewrapper( resp) { @override public printwriter getwriter() throws ioexception { return new printwriter(new outputstreamwriter(buffer, getcharacterencoding())); } @override public servletoutputstream getoutputstream() throws ioexception { return new servletoutputstream() { @override public void write(int b) throws ioexception { buffer.write(b); } }; } }; chain.dofilter(request, hsrw); byte[] gzipdata = gzip(buffer.tobytearray()); resp.addheader(content-encoding, gzip); resp.setcontentlength(gzipdata.length); servletoutputstream output = response.getoutputstream(); output.write(gzipdata); output.flush(); } else { chain.dofilter(request, response); } } // 用 gzip 压缩字节数组 private byte[] gzip(byte[] data) { bytearrayoutputstream byteoutput = new bytearrayoutputstream(10240); gzipoutputstream output = null; try { output = new gzipoutputstream(byteoutput); output.write(data); } catch (ioexception e) { } finally { try { output.close(); } catch (ioexception e) { } } return byteoutput.tobytearray(); } …… }
总结        细节决定成败,系统慢是由一个又一个不良的小细节造成的,所以开发初期做好充足的准备,开发中认真负责、不偷工减料,维护期更要注重代码质量,这样才能让我们的系统稳定高效。
        个人觉得一个产品的新版本质量可以从核心js文件看出来:如果核心js文件大小比上一版本大太多,明显在性能上就会有问题,我们要争做像谷歌、亚马逊这样优秀的团队--能够在功能升级的同时减小核心js文件大小。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product