一、高性能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
|