|
新產(chǎn)品為了效果,做的比較炫,用了很多的圖片和JS,所以前端的性能是很大的問題,分篇記錄前端性能優(yōu)化的一些小經(jīng)驗(yàn)。
第一篇:HTTP服務(wù)器
因tomcat處理靜態(tài)資源的速度比較慢,所以首先想到的就是把所有靜態(tài)資源(JS,CSS,image,swf)提到單獨(dú)的服務(wù)器,用更加快速的HTTP服務(wù)器,這里選擇了nginx 了,nginx相比apache,更加輕量級,配置更加簡單,而且nginx不僅僅是高性能的HTTP服務(wù)器,還是高性能的反向代理服務(wù)器。
目前很多大型網(wǎng)站都使用了nginx,新浪、網(wǎng)易、QQ等都使用了nginx,說明nginx的穩(wěn)定性和性能還是非常不錯的。
1. nginx 安裝(linux)
http://nginx.org/en/download.html 下載最新穩(wěn)定版本
根據(jù)自己需要的功能先下載對應(yīng)模板,這里下載了下面幾個模塊:
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 installWEB性能測試工具主要分為三種,一種是測試頁面資源加載速度的,一種是測試頁面加載完畢后頁面呈現(xiàn)、JS操作速度的,還有一種是總體上對頁面進(jìn)行評價分析,下面分別對這些工具進(jìn)行介紹,如果誰有更好的工具也請一起分享下。
Firebug:
Firebug 是firefox中最為經(jīng)典的開發(fā)工具,可以監(jiān)控請求頭,響應(yīng)頭,顯示資源加載瀑布圖:
HttpWatch :
httpwatch 功能類似firebug,可以監(jiān)控請求頭,響應(yīng)頭,顯示資源加載瀑布圖。但是httpwatch還能顯示GZIP壓縮信息,DNS查詢,TCP鏈接信息,個人在監(jiān)控http請求比較喜歡使用httpwatch,httpwatch包含IE和firefox插件。不過httpwatch專業(yè)版本是收費(fèi)的,免費(fèi)版本有些功能限制。
DynaTrace's Ajax Edition:dynaTrace 是本人常使用的1個免費(fèi)工具,該工具不但可以檢測資源加載瀑布圖,而且還能監(jiān)控頁面呈現(xiàn)時間,CPU花銷,JS分析和執(zhí)行時間,CSS解析時間的等。
Speed Tracer:
speed trace 是google chrome的1個插件,speed trace的優(yōu)勢點(diǎn)是用于監(jiān)控JS的解析執(zhí)行時間,還可以監(jiān)控頁面的重繪、回流,這個還是很強(qiáng)的(dynaTrace也能有這個功能)。 注:安裝這個插件,需要安裝 Google Chrome Developer Channel 版本,但是這個鏈接的地址在國內(nèi)好像打不開,如果打不開,請大家直接到這個地址去下載:
http://www.google.com/chrome/eula.html?extra=devchannel
Page Speed :
Page speed 是基于firebug的1個工具,主要可以對頁面進(jìn)行評分,總分100分,而且會顯示對各項(xiàng)的改進(jìn)意見,Page Speed也能檢測到JS的解析時間。
yslow :
yslow跟pge speed一樣是基于 firefox/firebug的插件,功能與page speed類似,對各種影響網(wǎng)站性能的因素進(jìn)行評分,yslow是yahoo的工具,本人也一直在使用,推薦一下。
webpagetest :
webpagetest 是1個在線進(jìn)行性能測試的網(wǎng)站,在該網(wǎng)站輸入你的url,就會生成1個url加載的時間瀑布圖,對所有加載的資源(css,js,image等等)列出優(yōu)化的清單,也是非常好用的工具。
縮小圖片大小
當(dāng)圖片很多的時候,減少圖片大小是提高下載速度最直接的方法。
1. 使用PNG8代替GIF(非動畫圖片),因?yàn)镻NG8在效果一樣的情況,圖片大小比GIF要小。2. 用fireworks處理PNG圖片,在我們產(chǎn)品中很多PNG圖片是美工直接用photoshop導(dǎo)出的,后來讓美工用fireworks處理PNG(大概的方式是選擇保存為PNG8,刪除背景色)。處理后100K的圖片大小基本減少了3/4,但圖片質(zhì)量也會有少許降低,要看自己是否能接受。
3. 使用Smush.it(http://www.smushit.com/ysmush.it/) 壓縮圖片,Smush.it是YUI團(tuán)隊(duì)做1個在線壓縮圖片的網(wǎng)站,該網(wǎng)站在不影響原圖片的質(zhì)量下去掉圖片中一些元數(shù)據(jù),所以可以放心使用該網(wǎng)站進(jìn)行壓縮,但這個壓縮比例也是比較有限的。
合并圖片和拆分圖片
1. CSS Sprites合并圖片以減少請求數(shù)來提高性能大家都知道。但不要把圖片合并太多,太多太大了,就會因?yàn)檫@1個圖片影響這個頁面的顯示了。
2. 有時候我們需要把1個大圖片拆分成多個小圖片,比如產(chǎn)品首頁圖片比較少,就1個很大的banner圖片,因?yàn)g覽器都可以并發(fā)下載圖片,所以如果不拆分,只使用1個大圖片的話,下載速度反而會比較慢。
透明圖片處理
IE6不能顯示透明的PNG圖片,是很多開發(fā)人員特別頭疼的事,分別介紹下幾種方式的優(yōu)缺點(diǎn)。
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');
}
外部JS的阻塞下載
所有瀏覽器在下載JS的時候,會阻止一切其他活動,比如其他資源的下載,內(nèi)容的呈現(xiàn)等等。至到JS下載、解析、執(zhí)行完畢后才開始繼續(xù)并行下載其他資源并呈現(xiàn)內(nèi)容。
有人會問:為什么JS不能像CSS、image一樣并行下載了?這里需要簡單介紹一下瀏覽器構(gòu)造頁面的原理,當(dāng)瀏覽器從服務(wù)器接收到了HTML文檔,并把HTML在內(nèi)存中轉(zhuǎn)換成DOM樹,在轉(zhuǎn)換的過程中如果發(fā)現(xiàn)某個節(jié)點(diǎn)(node)上引用了CSS或者 IMAGE,就會再發(fā)1個request去請求CSS或image,然后繼續(xù)執(zhí)行下面的轉(zhuǎn)換,而不需要等待request的返回,當(dāng)request返回后,只需要把返回的內(nèi)容放入到DOM樹中對應(yīng)的位置就OK。但當(dāng)引用了JS的時候,瀏覽器發(fā)送1個js request就會一直等待該request的返回。因?yàn)闉g覽器需要1個穩(wěn)定的DOM樹結(jié)構(gòu),而JS中很有可能有代碼直接改變了DOM樹結(jié)構(gòu),比如使用 document.write 或 appendChild,甚至是直接使用的location.href進(jìn)行跳轉(zhuǎn),瀏覽器為了防止出現(xiàn)JS修改DOM樹,需要重新構(gòu)建DOM樹的情況,所以就會阻塞其他的下載和呈現(xiàn)。
阻塞下載圖:下圖是訪問blogJava首頁的時間瀑布圖,可以看出來開始的2個image都是并行下載的,而后面的2個JS都是阻塞下載的(1個1個下載)。
嵌入JS的阻塞下載
嵌入JS是指直接寫在HTML文檔中的JS代碼。上面說了引用外部的JS會阻塞其后的資源下載和其后的內(nèi)容呈現(xiàn),哪嵌入的JS又會是怎樣阻塞的了,看下面的列2個代碼:
代碼
<div>
<ul>
<li>blogJava<span style="color: #800000;"/></li>
<li>CSDN<span style="color: #800000;"/></li>
<li>博客園<span style="color: #800000;"/></li>
<li>ABC<span style="color: #800000;"/></li>
<li>AAA<span style="color: #800000;"/></li>
</ul>
</div>
<script type="text/Javascript">
// 循環(huán)5秒鐘
{ var n = Number(new Date());
var n2 = Number(new Date());
while((n2 - n) (6*1000)){
n2 = Number(new Date());
}
</script>
<div>
<ul>
<li>MSN</li>
<li>GOOGLE</li>
<li>YAHOO</li>
</ul>
</div>http請求頭的數(shù)據(jù)量
我們先分析下請求頭,看看每次請求都帶了那些額外的數(shù)據(jù).下面是監(jiān)控的google的請求頭
代碼
Host www.google.com.hk
User-Agent Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.2.3) Gecko/20100401
Firefox/3.6.3 GTBDFff GTB7.0
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language zh-cn,en-us;q=0.7,en;q=0.3
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Proxy-Connection keep-alive
上一篇中我們說到了 如何減少請求數(shù),這次說說如何減少請求、響應(yīng)的數(shù)據(jù)量(即在網(wǎng)絡(luò)中傳輸?shù)臄?shù)據(jù)量),減少傳輸?shù)臄?shù)據(jù)量不僅僅可以加快頁面加載速度,更可以節(jié)約服務(wù)器帶寬,為你剩不少錢(好像很多機(jī)房托管都是按流量算錢的)。
GZIP壓縮
gzip是目前所有瀏覽器都支持的一種壓縮格式,IE6需要SP1及以上才支持(別說你還在用IE5,~_~)。gzip可以說是最方便而且也是最大減少響應(yīng)數(shù)據(jù)量的1種方法。
說它方便,是因?yàn)槟悴恍枰獮樗鼘懭魏晤~外的代碼,只需要在http服務(wù)器上加上配置都行了,現(xiàn)在主流的http 服務(wù)器都支持gzip,各種服務(wù)器的配置這里就不一一介紹(其實(shí)是我不知道怎么配),
nginx的配置可以參考我這篇文章:www.blogJava.NET/BearRui/archive/2010/01/29/web_performance_server.html
我們先看看gzip的壓縮比率能達(dá)到多少,這里用jquery 1.4.2的min和src2個版本進(jìn)行測試,使用nginx服務(wù)器,gzip壓縮級別使用的是:
注意看上圖的紅色部分,jquery src文件在啟用gzip后大小減少了70%
這張圖片可以看出就算是已經(jīng)壓縮過min.js在啟用gzip后大小也減少了65%。
別對圖片啟用gzip
在知道了gzip強(qiáng)大的壓縮能力后,你是否想對服務(wù)器上的所有文件啟用gzip了,先讓我們看看圖片中啟用gzip后會是什么情況。
hoho,1個gif圖片經(jīng)過gzip壓縮后反而變大了???這是因?yàn)閳D片本來就是一種壓縮格式,gzip不能再進(jìn)行壓縮,反而會添加1額外的頭部信息,所以圖片會變大。
在測試過程中,發(fā)現(xiàn)jpg的圖片經(jīng)過gzip壓縮后會變小,不知道為何,可能跟圖片壓縮方式有關(guān)。不過壓縮比率也比較小,所以就算是jpg,建議也不要開啟gzip壓縮。
比較適合啟用gzip壓縮的文件有如下這些:
1. Javascript
2. CSS
3. HTML,xml
4. plain text
別亂用cookie
現(xiàn)在幾乎沒有哪個網(wǎng)站不使用cookie了,可是該怎么使用cookie比較合適了,cookie有幾個重要的屬性:path(路徑),domain(域),expires(過期時間)。瀏覽器就是根據(jù)這3個屬性來判斷在發(fā)送請求的時候是否需要帶上這個cookie。cookie使用最好的方式,就是當(dāng)請求的資源需要cookie的時候才帶上該cookie。其他任何請求都不帶上cookie。但事實(shí)上很多人在使用 cookie的時候已經(jīng)習(xí)慣性的設(shè)置成:path=/ domain=.domain.com。這樣的結(jié)果就是不管任何請求都會帶上cookie,就算你是請求的圖片(img.domain.com)、靜態(tài)資源服務(wù)器(res.domain.com)這些根本不需要cookie的資源,瀏覽器照樣會帶上這些沒用的cookie。咱們一起來看現(xiàn)實(shí)中的1個列子,博客園(www.cnblogs.com):
先看看博客園的cookie是怎么設(shè)置的,下面是firefox查看博客園cookie的截圖:
cnblogs總共有5個cookie值,而且全部設(shè)置都是 path=/ domain=.cnblogs.com。知道了cookie的設(shè)置后,我們再來監(jiān)控下博客園首頁的請求,監(jiān)控的統(tǒng)計(jì)信息如下:
總請求數(shù):39(其中圖片22個,JS7個,css2個)。
其中js、css、image 主要來自3個靜態(tài)資源服務(wù)器: common.cnblogs.com , pic.cnblogs.com ,static.cnblogs.com
再看其中1個請求圖片(http://static.cnblogs.com/images/a4/banner_job.gif)的請求頭:
Host static.cnblogs.com
User-Agent Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.2.3) Gecko/20100401
Firefox/3.6.3 GTBDFff GTB7.0
Accept image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language zh-cn,en-us;q=0.7,en;q=0.3
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Proxy-Connection keep-alive
Referer http://www.cnblogs.com/
Cookie __gads=ID=a15d7cb5c3413e56:T=1272278620:S=ALNI_MZNMr6_d_PCjgkJNJeEQXkmZ3bxTQ;
__utma=226521935.1697566422.1272278366.1272278366.1272278366.1;
__utmb=226521935.2.10.1272278366; __utmc=226521935;
__utmz=226521935.1272278367.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
本篇文章主要討論下目前JS,CSS 合并、壓縮、緩存管理存在的一些問題,然后分享下自己項(xiàng)目中用到的1個處理方案,并提供1個實(shí)例下載。
存在的問題:合并、壓縮文件主要有2方面的問題:
1. 每次發(fā)布的時候需要運(yùn)行一下自己寫的bat文件或者其他程序把文件按照自己的配置合并和壓縮。
2. 因生產(chǎn)環(huán)境和開發(fā)環(huán)境需要加載的文件不一樣,生產(chǎn)環(huán)境為了需要加載合并、壓縮后的文件,而開發(fā)環(huán)境為了修改、調(diào)試方便,需要加載非合并、壓縮的文件,所以我們常常需要在JSP中類似與下面的判斷代碼:
代碼
<c:if test="${env=='prod'}">
<script type="text/Javascript" src="/js/all.js"></script>
</c:if>
<c:if test="${env=='dev'}">
<script type="text/Javascript" src="/js/1.js"></script>
<script type="text/Javascript" src="/js/2.js"></script>
<script type="text/Javascript" src="/js/3.js"></script>
</c:if>頁面呈現(xiàn)流程
在討論頁面重繪、回流之前。需要對頁面的呈現(xiàn)流程有些了解,頁面是怎么把html結(jié)合css等顯示到瀏覽器上的,下面的流程圖顯示了瀏覽器對頁面的呈現(xiàn)的處理流程。可能不同的瀏覽器略微會有些不同。但基本上都是類似的。
1. 瀏覽器把獲取到的html代碼解析成1個Dom樹,html中的每個tag都是Dom樹中的1個節(jié)點(diǎn),根節(jié)點(diǎn)就是我們常用的document對象 (<html> tag)。dom樹就是我們用firebug或者IE Developer Toolbar等工具看到的html結(jié)構(gòu),里面包含了所有的html tag,包括display:none隱藏,還有用JS動態(tài)添加的元素等。
2. 瀏覽器把所有樣式(主要包括css和瀏覽器的樣式設(shè)置)解析成樣式結(jié)構(gòu)體,在解析的過程中會去掉瀏覽器不能識別的樣式,比如IE會去掉-moz開頭的樣式,而firefox會去掉_開頭的樣式。
3、dom tree和樣式結(jié)構(gòu)體結(jié)合后構(gòu)建呈現(xiàn)樹(render tree),render tree有點(diǎn)類似于dom tree,但其實(shí)區(qū)別有很大,render tree能識別樣式,render tree中每個node都有自己的style,而且render tree不包含隱藏的節(jié)點(diǎn)(比如display:none的節(jié)點(diǎn),還有head節(jié)點(diǎn)),因?yàn)檫@些節(jié)點(diǎn)不會用于呈現(xiàn),而且不會影響呈現(xiàn)的,所以就不會包含到 render tree中。注意 visibility:hidden隱藏的元素還是會包含到render tree中的,因?yàn)関isibility:hidden 會影響布局(layout),會占有空間。根據(jù)css2的標(biāo)準(zhǔn),render tree中的每個節(jié)點(diǎn)都稱為box(Box dimensions),box所有屬性:width,height,margin,padding,left,top,border等。
4. 一旦render tree構(gòu)建完畢后,瀏覽器就可以根據(jù)render tree來繪制頁面了。
回流與重繪
1. 當(dāng)render tree中的一部分(或全部)因?yàn)樵氐囊?guī)模尺寸,布局,隱藏等改變而需要重新構(gòu)建。這就稱為回流(其實(shí)我覺得叫重新布局更簡單明了些)。每個頁面至少需要一次回流,就是在頁面第一次加載的時候。
2. 當(dāng)render tree中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風(fēng)格,而不會影響布局的,比如background-color。則就叫稱為重繪。
注:從上面可以看出,回流必將引起重繪,而重繪不一定會引起回流。
什么操作會引起重繪、回流
其實(shí)任何對render tree中元素的操作都會引起回流或者重繪,比如:
1. 添加、刪除元素(回流+重繪)
2. 隱藏元素,display:none(回流+重繪),visibility:hidden(只重繪,不回流)
3. 移動元素,比如改變top,left(jquery的animate方法就是,改變top,left不一定會影響回流),或者移動元素到另外1個父元素中。(重繪+回流)
4. 對style的操作(對不同的屬性操作,影響不一樣)
5. 還有一種是用戶的操作,比如改變?yōu)g覽器大小,改變?yōu)g覽器的字體大小等(回流+重繪)
讓我們看看下面的代碼是如何影響回流和重繪的:
代碼
var s = document.body.style;
s.padding = "2px"; // 回流+重繪
s.border = "1px solid red"; // 再一次 回流+重繪
s.color = "blue"; // 再一次重繪
s.backgroundColor = "#ccc"; // 再一次 重繪
s.fontSize = "14px"; // 再一次 回流+重繪
// 添加node,再一次 回流+重繪
document.body.appendChild(document.createTextNode('abc!'));
it知識庫:高性能WEB開發(fā),轉(zhuǎn)載需保留來源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。