| 一、高性能WEB开发之HTTP服务器 新产品为了效果,做的比较炫,用了很多的图片和JavaScript,所以前端的性能是很大的问题,分篇记录前端性能优化的一些小经验。 第一篇:HTTP服务器 因tomcat处理静态资源的速度比较慢,所以首先想到的就是把所有静态资源(JS,CSS,image,swf) 提到单独的服务器,用更加快速的HTTP服务器,这里选择了nginx了,nginx相比apache,更加轻量级, 配置更加简单,而且nginx不仅仅是高性能的HTTP服务器,还是高性能的反向代理服务器。 目前很多大型网站都使用了nginx,新浪、网易、QQ等都使用了nginx,说明nginx的稳定性和性能还是非常不错的。 1. nginx 安装(linux) http://nginx.org/en/download.html 下载最新稳定版本 根据自己需要的功能先下载对应模板,这里下载了下面几个模块: openssl-0.9.8l,zlib-1.2.3,pcre-8.00 编译安装nginx: 
                           
                            | ./configure   --without-http_rewrite_module
 --with-http_ssl_module
 --with-openssl=../../lib/openssl-0.9.8l
 --with-zlib=../../lib/zlib-1.2.3
 --with-pcre=../../lib/pcre-8.00
 --prefix=/usr/local/nginx
 
 make
 
 make install
 |  2、nginx处理静态资源的配置 
                           
                            | #启动GZIP压缩CSS和JS  gzip  on;
 # 压缩级别 1-9,默认是1,级别越高压缩率越大,当然压缩时间也就越长
 gzip_comp_level 4;
 # 压缩类型
 gzip_types text/css application/x-javascript;
 
 # 定义静态资源访问的服务,对应的域名:res.abc.com
 server {
 listen       80;
 server_name  res.abc.com;
 
 # 开启服务器读取文件的缓存,
 open_file_cache max=200 inactive=2h;
 open_file_cache_valid 3h;
 open_file_cache_errors off;
 
 charset utf-8;
 
 # 判断如果是图片或swf,客户端缓存5天
 location ~* ^.+.(ico|gif|bmp|jpg|jpeg|png|swf)$ {
 root   /usr/local/resource/;
 access_log off;
 index  index.html index.htm;
 expires 5d;
 }
 
 # 因JS,CSS改动比较频繁,客户端缓存8小时
 location ~* ^.+.(js|css)$ {
 root   /usr/local/resource/;
 access_log off;
 index  index.html index.htm;
 expires 8h;
 }
 
 # 其他静态资源
 location / {
 root   /usr/local/resource;
 access_log off;
 expires 8h;
 }
 }
 |  3、nginx 反向代理设置 
                           
                            | # 反向代理服务,绑定域名www.abc.com  server {
 listen       80;
 server_name  www.abc.com;
 
 charset utf-8;
 
 # BBS使用Discuz!
 # 因反向代理为了提高性能,一部分http头部信息不会转发给后台的服务器,
 # 使用proxy_pass_header 和 proxy_set_header 把有需要的http头部信息转发给后台服务器
 location ^~ /bbs/ {
 root   html;
 access_log off;
 index index.php;
 # 转发host的信息,如果不设置host,在后台使用request.getServerName()取到的域名不是www.abc.com,而是127.0.0.1
 proxy_set_header Host $host;
 # 因Discuz! 为了安全,需要获取客户端User-Agent来判断每次POST数据是否跟第一次请求来自同1个浏览器,
 # 如果不转发User-Agent,Discuz! 提交数据就会报"您的请求来路不正确,无法提交"的错误
 proxy_pass_header User-Agent;
 proxy_pass http://127.0.0.1:8081;
 }
 
 # 其他请求转发给tomcat
 location / {
 root   html;
 access_log off;
 index index.jsp;
 proxy_pass http://127.0.0.1:8080;
 }
 
 error_page   500 502 503 504  /50x.html;
 location = /50x.html {
 root   html;
 }
 }
 |  nginx详细配置参考:http://wiki.nginx.org/ PS:如果安装提示GCC not found,运行下面命令安装就可以(apt-get install 
                          build-essential),仅限debian 二、高性能WEB开发之Web性能测试工具推荐 WEB性能测试工具主要分为三种,一种是测试页面资源加载速度的,一种是测试页面加载完毕后页面呈现、JS操作速度的,还有一种是总体上对页面进行评价分析,下面分别对这些工具进行介绍,如果谁有更好的工具也请一起分享下。 Firebug: Firebug 是firefox中最为经典的开发工具,可以监控请求头,响应头,显示资源加载瀑布图: 
 HttpWatch : httpwatch 功能类似firebug,可以监控请求头,响应头,显示资源加载瀑布图。但是httpwatch还能显示GZIP压缩信息,DNS查询,TCP链接信息,个人在监控http请求比较喜欢使用httpwatch, httpwatch包含IE和firefox插件。不过httpwatch专业版本是收费的,免费版本有些功能限制。 
 DynaTrace's Ajax Edition: dynaTrace 是本人常使用的1个免费工具,该工具不但可以检测资源加载瀑布图,而且还能监控页面呈现时间,CPU花销,JS分析和执行时间,CSS解析时间的等。 
 Speed Tracer: speed trace 是google chrome的1个插件,speed 
                          trace的优势点是用于监控JS的解析执行时间,还可以监控页面的重绘、回流,这个还是很强的(dynaTrace也能有这个功能)。 
 注:安装这个插件,需要安装 Google Chrome Developer Channel 版本,但是这个链接的地址在国内好像打不开,如果打不开,请大家直接到这个地址去下载: http://www.google.com/chrome/eula.html?extra=devchannel Page Speed : Page speed 是基于firebug的1个工具,主要可以对页面进行评分,总分100分,而且会显示对各项的改进意见,Page 
                          Speed也能检测到JS的解析时间。 
 yslow : yslow跟pge speed一样是基于 firefox\firebug的插件,功能与page 
                          speed类似,对各种影响网站性能的因素进行评分,yslow是yahoo的工具,本人也一直在使用,推荐一下。 
 webpagetest : webpagetest 是1个在线进行性能测试的网站,在该网站输入你的url,就会生成1个url加载的时间瀑布图,对所有加载的资源(css,js,image等等)列出优化的清单,也是非常好用的工具。 
 三、高性能WEB开发之图片篇 在该网站在不影响原图片的质量下去掉图片中一些元数据,那么这怎么去实现呢?本文就主要告诉你如何高性能WEB开发之图片篇 一、缩小图片大小 当图片很多的时候,减少图片大小是提高下载速度最直接的方法。 1. 使用PNG8代替GIF(非动画图片),因为PNG8在效果一样的情况,图片大小比GIF要小。 2. 用fireworks处理PNG图片,在我们产品中很多PNG图片是美工直接用photoshop导出的, 后来让美工用fireworks处理PNG(大概的方式是选择保存为PNG8,删除背景色)。 处理后100K的图片大小基本减少了3/4,但图片质量也会有少许降低,要看自己是否能接受。 3. 使用Smush.it(http://www.smushit.com/ysmush.it/)压缩图片,Smush.it是YUI团队做1个在线压缩图片的网站, 该网站在不影响原图片的质量下去掉图片中一些元数据,所以可以放心使用该网站进行压缩, 但这个压缩比例也是比较有限的。 二、合并图片和拆分图片 1. CSS Sprites合并图片以减少请求数来提高性能大家都知道。但不要把图片合并太多,太多太大了, 就会因为这1个图片影响这个页面的显示了。 2. 有时候我们需要把1个大图片拆分成多个小图片,比如产品首页图片比较少,就1个很大的banner图片, 因浏览器都可以并发下载图片,所以如果不拆分,只使用1个大图片的话,下载速度反而会比较慢 三、透明图片处理 IE6不能显示透明的PNG图片,是很多开发人员特别头疼的事,分别介绍下几种方式的优缺点。 1.使用AlphaImageLoader,IE6支持filter,使用下面的CSS代码,可以让IE6支持PNG 
                           
                            | #some-element {  background: url(image.png);
 _background: none;
 _filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='image.png', sizingMethod='crop');
 }
 |  优点:使用简单 缺点:性能损耗很大,AlphaImageLoader会花费很多资源去处理透明图片,使用AlphaImageLoader,IE使用内存会迅速上升。 而且AlphaImageLoader所有处理都在同1个线程中同步进行,所以当AlphaImageLoader多的时候,会阻塞UI的渲染。 使用_filter,IE7也可以识别,其实IE7是可以识别PNG透明图片的,如果在IE7下使用上面代码,IE7不会直接使用图片,而是使用AlphaImageLoader。 注:个人建议尽量避免使用AlphaImageLoader 2. JS处理 使用DD_belatedPNG(http://www.dillerdesign.com/experiment/DD_belatedPNG/),可以很简单的对界面上所有的透明图片进行同一处理。 优点:使用简单(比AlphaImageLoader还简单) 缺点:当页面上需要处理的图片比较多的时候,速度也比较慢,而且不能动态改变图片。 3. VML IE6支持VML,VML可以使用透明图片,代码如下: 修改html代码头部 
                           
                            | html  xmlns ="http://www.w3.org/1999/xhtml"  xmlns:v >   head >
 style  type ="text/css" >
 v\:* { behavior : url(#default#VML) ; }
 span style="color: rgb(128, 0, 0);">style >
 span style="color: rgb(128, 0, 0);">head >
 body >
 v:image  src ="image.png"   />
 span style="color: rgb(128, 0, 0);">body >
 span style="color: rgb(128, 0, 0);">html >
 |  优点:性能好,速度快 缺点:使用复杂,而且不支持firefox等浏览器,需要判断不同的浏览器输出不同的HTML代码。 四、多域名下载图片 因每个浏览器对同1个域名同时只能发送固定的请求,比如IE6好像是2个,所以可以对图片资源开通多个域名进行请求, 比如img1.abc.com,img2.abc.com。但域名不要开启太多,因为解析域名和打开新的连接都需要消耗时间,域名多了,说不定反而会更慢。一般2-4个域名就够了。 五、IE6下缓存背景图片 IE6背景图片缓存是个麻烦事,很多人知道使用下面的JS来让IE6缓存背景图片 
                           
                            | try{  document.execCommand("BackgroundImageCache", false, true);
 }catch(e){}
 |  但是这样做的效果并不是非常好,当出现鼠标移动改变背景图片的时候,IE6老是会发送1个图片请求(尽管该背景图片已经下载), 虽然返回结果是304,但还是要花费不少时间。在这种情况下,可以使用下面1个变通的方式来处理, 在页面上直接使用1个DIV元素来加载该图片,这样加载图片就能真正被缓存,鼠标移动也不会发送请求了。 六、预加载图片 使用下面代码可以在页面加载完毕后预加载下1个页面的图片,当进入下1个页面就不用再下载图片了。 
                           
                            | window.onload=function(){  var img = new Image();
 img.src = "images/image.png";
 img = null;
 };
 |  四、高性能WEB开发之疯狂的HTML压缩 在“JS、CSS的合并、压缩、缓存管理”一文中说到自己写过的1个自动合并、压缩JS,CSS,并添加版本号的组件。这次把压缩html的功能也加入到该组件中,流程很简单,就是在程序启动(contextInitialized 
                          or Application_Start)的时候扫描所有html,jsp(aspx)进行压缩。 上一篇随笔中网友 skyaspnet 问我如何压缩HTML,当时回答是推荐他使用gzip,后来想想,要是能把所有的html,jsp(aspx)在运行前都压缩成1行未免不是一件好事啊。一般我们启动gzip都比较少对html启动gzip,因为现在的html都是动态的,不会使用浏览器缓存,而启用gzip的话每次请求都需要压缩,会比较消耗服务器资源,对js,css启动gzip比较好是因为js,css都会使用缓存。我个人觉得的压缩html的最大好处就是一本万利,只要写好了一次,以后所有程序都可以使用,不会增加任何额外的开发工作。 在“JS、CSS的合并、压缩、缓存管理”一文中说到自己写过的1个自动合并、压缩JS,CSS,并添加版本号的组件。这次把压缩html的功能也加入到该组件中,流程很简单,就是在程序启动(contextInitialized 
                          or Application_Start)的时候扫描所有html,jsp(aspx)进行压缩。 压缩的注意事项: 实现的方式主要是用正则表达式去查找,替换。在html压缩的时候,主要要注意下面几点: 1. pre,textarea 标签里面的内容格式需要保留,不能压缩。 2. 去掉html注释的时候,有些注释是不能去掉的,比如:<!--[if IE 6]> ..... 
                          <![endif]--> 3. 压缩嵌入式js中的注释要注意,因为可能注释符号会出现在字符串中,比如: var url = "http://www.cnblogs.com"; 
                          // 前面的//不是注释 去掉JS换行符的时候,不能直接跟一下行动内容,需要有空格,考虑下面的代码: 如果不带空格,则变成elsereturn。 4. jsp(aspx) 中很有可能会使用嵌入一些服务器代码,这个时候也需要单独处理,里面注释的处理方法跟js的一样。 源代码: 下面是java实现的源代码,也可以 猛击此处 下载该代码,相信大家都看的懂,也很容易改成net代码: 使用注意事项: 使用了上面方法后,再运行程序,是不是发现每个页面查看源代码的时候都变成1行啦,还不错吧,但是在使用的时候还是要注意一些问题: 1. 嵌入js本来想调用yuicompressor来压缩,yuicompressor压缩JS前,会先编译js是否合法,因我们嵌入的js中可能很多会用到一些服务器端代码,比如 
                          var now = ,这样的代码会编译不通过,所以无法使用yuicompressor。 最后只能自己写压缩JS代码,自己写的比较粗燥,所以有个问题还解决,就是如果开发人员在一句js代码后面没有加分号的话,压缩成1行就很有可能出问题。所以使用这个需要保证每条语句结束后都必须带分号。 2. 因为是在程序启动的时候压缩所有jsp(aspx),所以如果是用户请求的时候动态产生的html就无法压缩。 五、高性能web开发之网络传输环节 本节主要谈网络传输环节,利用HTTP 1.1的长连接特性,使得在一定程度上,服务器可以主动推送数据(减少了很多不必要的轮询)。 1.减少请求数. 1. 缓存,使用Expires 等设置过期时间;如果内容没有过期就不发送请求 2. 合并小体积内容,例如吧数量众多的小图片放在一个图片,之后用css部分呈现(大体积的内容就别合并了) 3. 延迟加载;部分内容,例如图片在页面呈现的时候才加载 (常用的就是滚动条到了以后才加载);减少不必要的请求 4. 合并重复内容和文件 5. 考虑使用第三方CDN资源,例如jQuery有免费的CDN,有些用户已经在其他网站访问过该内容了,那么到我们的网站加载就更快了 
                          (而且使用CDN降低对我们服务器的压力) 6. 使用HTML 5 中的Local Storage等保存数据 2.减少响应内容的体积. 1. 适当的时候只返回响应头304 (HTTP缓存,如ETag等) 2. 使用Gzip等压缩文件内容 3. 使用免费的第三方工具,压缩css,js和html等文件的大小 (例如我们常见的 
                          jquery.min.js) 4. 适当使用Ajax操作 5. 在适当的时候,将样式,HTML和数据分离 (数据量很大的时候极大减小文件体积) 
                           
                            | <ul id="id"> <li style="一大堆的样式">数据 </li>
 <li style="一大堆的样式">数据 </li>
 <li style="一大堆的样式">数据 </li>
 </ul>
 分成HTML 样式 和数据3部分
 
 HTML
 <ul id="id">
 <li></li>
 <!-- 如果使用数据模板等方式 只需要保留一个Li 否则需要多个 -->
 </ul>
 |  样式保存在CSS文件中一些基本的小常识 虽然有很多个li 不用给每个li指定class 数据 1. 使用JSON返回 (如果觉得麻烦也可以嵌入在页面中) 2. 选择体积更小的数据格式,例如JSON一般就比XML体积来的小 (都经过压缩以后还是更小) 3. 在设计上,只传送变化的部分数据 (例如要获取100条数据,可能已经加载了90条,那么再加载10条就好了) 4. 移除请求和响应中不必要的HTTP Header (例如WCF Restful 
                          service中有的时候要传递表明当前数据是JSON还是XML的HTTP Header) 5. 部分功能,如压缩会消耗CPU, 如ajax等会增加开发工作量,请谨慎选择 3.增加请求并发数. 1. RFC中,浏览器对于同一个域名下的资源只能使用2个线程同时进行访问(很多新的浏览器支持6个或者更多);解决方法是使用子域名,例如1.abc.com 
                          2.abc.com 
                           
                            | <img src ="1.abc.com/1.png" /> <img src ="1.abc.com/2.png" />
 <img src ="2.abc.com/3.png" />
 <img src ="2.abc.com/4.png" />
 <img src ="3.abc.com/5.png" />
 <img src ="3.abc.com/6.png" />
 <img src ="4.abc.com/7.png" />
 <img src ="4.abc.com/8.png" />
 |  2. 将一个超大的文件(例如有些人喜欢吧整个网站的js都放在一个文件)拆成一系列的中小文件 
                          (有利于并发加载和缓存!)这个文件大小的Size选择很重要 我个人建议是10k-200k (依赖于网络) 3. 上一条并没有和1-2冲突,文件太小太多也不行,文件太少太大也不行,这是一个平衡的问题 4. 通过分拆文件,使得最常用页面(例如首页)的加载速度变快了 5. 控制加载顺序,例如先加载页面大体结构,然后多个javascript异步请求加载数据(把一个大的html变为多个小的html片段) 4.其他特殊技术.  利用HTTP 1.1的长连接特性,使得在一定程度上,服务器可以主动推送数据(减少了很多不必要的轮询) 5.工具. 1. Fiddler (Free) 2. FireDebug (Free) 3. HttpWatch |