明輝手游網(wǎng)中心:是一個免費提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

對于HTML5中優(yōu)化性能的詳細說明

[摘要]HTML5性能優(yōu)化--減少重繪 在HTML頁面完成展現(xiàn)之后,動態(tài)改變頁面元素或調(diào)整CSS樣式都會引起瀏覽器重繪,性能的損耗直接取決于動態(tài)改變的范圍:如果只是改變一個元素的顏色之類的信息則只會重繪該元素;而如果是增刪節(jié)點或調(diào)整節(jié)點位置則會引起其兄弟節(jié)點也一并重繪。 減少重...

HTML5性能優(yōu)化

--減少重繪

在HTML頁面完成展現(xiàn)之后,動態(tài)改變頁面元素或調(diào)整CSS樣式都會引起瀏覽器重繪,性能的損耗直接取決于動態(tài)改變的范圍:如果只是改變一個元素的顏色之類的信息則只會重繪該元素;而如果是增刪節(jié)點或調(diào)整節(jié)點位置則會引起其兄弟節(jié)點也一并重繪。

減少重繪并不是說不要重繪,而是要注意重繪范圍:①改動的DOM元素越深則影響越小,所以盡量深入節(jié)點改動;②對某些DOM樣式有多重變動盡量合并到一起修改。

以改變一個<a>標簽的背景色、寬度和顏色為例。


<a href="javascript:void(0);" id="example">傳統(tǒng)的代碼</a> 
<script> 
 var example = document.getElementById("example"); 
 example.ondblclick = function() { 
 example.style.backgroundColor = "red"; 
 example.style.width = "200px"; 
 example.style.color = "white"; 
 } 
</script>


以上會執(zhí)行3次重繪,而通過CSS代替javascript多次執(zhí)行則只進行一次重繪。


<style> 
 .dblClick { 
 width: 200px; 
 background: red; 
 color: white; 
 } 
</style> 
<a href="javascript:;" id="example">CSS優(yōu)化的代碼</a> 
<script> 
 var example = document.getElementById("example"); 
 example.ondblclick = function() { 
 example.className = "dblClick"; 
 } 
</script>

避免腳本阻塞加載

當(dāng)瀏覽器在解析常規(guī)的script標簽時,它需要等待script下載完畢,再解析執(zhí)行,而后續(xù)的HTML代碼只能等待。CSS文件引入要放在<head>頭部,因為這是HTML渲染必備元素。為了避免阻塞加載,應(yīng)把腳本放到文檔的末尾,而CSS是需要放在頭部的!


<head>
<link rel="stylesheet" href="common.css">......<script src="example.js"></script>
</body>

--避免節(jié)點深層級嵌套

深層級嵌套的節(jié)點在初始化構(gòu)建時往往需要更多的內(nèi)存占用,并且在遍歷節(jié)點時也會更慢些,這與瀏覽器構(gòu)建DOM文檔的機制有關(guān)。瀏覽器會把整個HTML文檔的結(jié)構(gòu)存儲為DOM“樹”結(jié)構(gòu)。當(dāng)文檔節(jié)點的嵌套層次越深,構(gòu)建的DOM樹層次也會越深。

如下代碼,完全能夠去掉<p>或<span>其中一個標簽。


<p>
  <span>
    <label>嵌套</label>
  </span>
</p>


頁面緩存

通常不設(shè)置緩存的情況下,每次刷新頁面都會重新讀取服務(wù)器的文件,而如果設(shè)置緩存之后,所有文件都可以從本地取得,這樣明顯極大提高了頁面效率。

我們可以通過設(shè)置頁面頭的expires來定義頁面過期時間,將過期時間定久一點就達到了“永久”緩存。


<meta http-equiv="expires" content="Sunday 26 October 2099 01:00 GMT" />

當(dāng)然,如果你的項目代碼有變更,因為客戶端緩存了文件就得不到最新的文件,勢必造成顯示錯誤;谶@個問題的解決方案就是給鏈接文件加一個時間戳,如果時間戳有變化,瀏覽器會認為是新文件,就會向服務(wù)器請求最新文件。


<script src="example2014-6-17.js">
</script>//如果是JSP,可以用EL表達式來取時間戳信息,這樣管理更加方便
<script src="example${your time param}.js">
</script>//或者這樣的寫法更優(yōu)秀:
<script src="example.js?time=2014-6-7"></script>
<script src="example.js?time=${your time param}"></script>


壓縮合并文件

所有涉及到請求數(shù)據(jù)的文件盡量做壓縮,比如Javascript文件、css文件及圖片文件,特別是圖片文件,如果沒有高清晰要求,完全可以壓縮后再使用。

數(shù)量少體積大的文件要比數(shù)量多體積小的文件加載速度快,所以有時候可以考慮將多個js文件、多個css文件合并在一起。

除此之外減少HTML文檔大小還可以采取下面幾種方法:

①刪掉HTM文檔對執(zhí)行結(jié)果無影響的空格空行和注釋

②避免Table布局

③使用HTML5

--HTML+CSS3+Javascript各司其職

讓三元素各司其職才能做出高性能的網(wǎng)頁:HTML是頁面之本也是內(nèi)容之源,有了它就能跟CSS和Javascript交互;CSS3可以說是展現(xiàn)大師,而且日漸強大的CSS能代替Javascript做很多動態(tài)的事情如漸變、移動等動態(tài)效果;Javascript是動態(tài)數(shù)據(jù)之王,舊瀏覽器依靠js來完成動態(tài)效果展現(xiàn),但現(xiàn)在的CSS也能完成js的工作,所以盡量將工作交給css,這樣會獲得更好的性能。(這個說得有點大)

--圖像合并實現(xiàn)CSS Sprites

圖像合并其實就是把網(wǎng)頁中一些背景圖片整合到一張圖片文件中,再利用CSS 的“background-image”,“background- repeat”,“background-position”的組合進行背景定位,background-position可以用數(shù)字能精確的定位出背景圖片的位置。

一個頁面要用到多個圖標,完全可以將多個圖標合并成一個圖,然后只需要發(fā)一次圖片請求,通過css定位分割圖標即可。

--避免使用Iframe

使用iframe并不會增加同域名下的并行下載數(shù),瀏覽器對同域名的連接總是共享瀏覽器級別的連接池,在頁面加載過程中iframe元素還會阻塞父文檔onload事件的觸發(fā)。并且iframe是html標簽中最消耗資源的標簽,它的開銷比p、SCRIPT、STYLE等DOM高1~2個數(shù)量級。

避免onload事件被阻塞,可使用JavaScript動態(tài)的加載iframe元素或動態(tài)設(shè)置iframe的src屬性(但其僅在高級瀏覽器IE9及以上有效)。


<iframe id="if"></iframe>
document.getElementById("if").setAttribute("src","url");

--多域名請求

一般來說,瀏覽器對于相同域名的圖片,最多用2-4個線程并行下載(不同瀏覽器的并發(fā)下載數(shù)是不同的)。而相同域名的其他圖片,則要等到其他圖片下載完后才會開始下載。

有時候,圖片數(shù)據(jù)太多,一些公司的解決方法是將圖片數(shù)據(jù)分到多個域名的服務(wù)器上,這在一方面是將服務(wù)器的請求壓力分到多個硬件服務(wù)器上,另一方面,是利用了瀏覽器的特性。(大家可以去新浪、騰訊門戶網(wǎng)站查看,這些大型站點同一頁面加載的圖片可能由多個站點提供)

注:一個HTML請求的域名也不要太多(2~3個差不多),多了可能造成不同服務(wù)器連接時間差異,反而影響速度。

--避免空鏈接屬性

如<img src=""><a href="">這樣的設(shè)置方式是非常不可取的,即使鏈接為空,在舊的瀏覽器也會以固定步驟發(fā)送請求信息。

另外<a href="#"></a>也不可取,最好的方式是在鏈接中加一個空的js代碼<a href="javascript:void();"></a>

--使用圖像的BASE64編碼

base64是一串字符串,他可以代表一個圖片的所有信息,也就是可以通過<img src="data:image/png;base64,S">(S表示一串base64碼)來顯示圖片,這種方式不需要再向服務(wù)器發(fā)送請求,完全由瀏覽器解析成圖片。

目前高級瀏覽器都支持此功能,但要注意兩點:①低版本瀏覽器(如IE7)不支持;②base64字符串長度隨圖片的大小及復(fù)雜度成正比,base64也像URL一樣,也有超出長度的情況(在IE8下很常見)。所以要根據(jù)情況來使用。

--顯式設(shè)置圖片的寬高

如果HTML里的圖片沒有指定尺寸(寬和高),或者代碼描述的尺寸與實際圖片的尺寸不符時,瀏覽器則要在圖片下載完成后再“回溯”該圖片并重新顯示,這會消耗額外時間。


<iframe id="if"></iframe>
document.getElementById("if").setAttribute("src","url");

--顯式指定文檔字符集

如果瀏覽器不能獲知頁面的編碼字符集,一般都會在執(zhí)行腳本和渲染頁面前,把字節(jié)流緩存,然后再搜索可進行解析的字符集,或以默認的字符集來解析頁面代碼,這會導(dǎo)致消耗不必要的時間。


<iframe id="if"></iframe>
document.getElementById("if").setAttribute("src","url");

--漸進式增強設(shè)計

漸進式增強設(shè)計的通俗解釋就是:首先寫一段滿足所有瀏覽器的基本樣式,再在后面針對不同高級瀏覽器編寫更漂亮的樣式

如下代碼,所有瀏覽器都支持background-color: #2067f5;滿足了瀏覽器基本現(xiàn)實需求,而后面的background-image: -webkit-gradient等則為不同高級瀏覽器使用,只要瀏覽器識別就能執(zhí)行這段代碼(不識別,CSS也不會報錯只會直接忽略)。


<p class="someClass"></p> 
.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); 
}

--懶加載與預(yù)加載

預(yù)加載和懶加載,是一種改善用戶體驗的策略,它實際上并不能提高程序性能,但是卻可以明顯改善用戶體驗或減輕服務(wù)器壓力。

預(yù)加載表示當(dāng)前用戶在請求到需要的數(shù)據(jù)之后,頁面自動預(yù)加載下一次用戶可能要看的數(shù)據(jù),這樣用戶下一次操作的時候就立刻呈現(xiàn),依次類推。

懶加載表示用戶請求什么再顯示什么,如果一個請求要響應(yīng)的時間非常長,就不推薦懶加載。

--Flush機制

當(dāng)一個頁面非常大,內(nèi)容非常多,可以采用flush的形式分部分返回給頁面,這樣能告訴用戶我正在工作,顯示一部分內(nèi)容比白屏等很長時間要好得多。在Java Web技術(shù)中,實現(xiàn)Flush非常簡單,只要調(diào)用 HttpServletResponse.getWriter輸出流的flush方法,就可以將已經(jīng)完成加載的內(nèi)容寫回給客戶端。

這種方式只適用于返回數(shù)據(jù)特別多、請求時間特別長的情況,常規(guī)數(shù)據(jù)還是用正常的實時全部返回最佳。這種實現(xiàn)方式實際會增加瀏覽器渲染時間和用戶整體等待時間,但從用戶體驗上會更加優(yōu)秀。

  • 性能之服務(wù)器優(yōu)化

--CDN機制

所謂的CDN,就是一種內(nèi)容分發(fā)網(wǎng)絡(luò),它采用智能路由和流量管理技術(shù),及時發(fā)現(xiàn)能夠給訪問者提供最快響應(yīng)的加速節(jié)點,并將訪問者的請求導(dǎo)向到該加速節(jié)點,由該加速節(jié)點提供內(nèi)容服務(wù)。

通俗點說,你在成都(瀏覽器)購買了北京賣家(服務(wù)器)的產(chǎn)品,北京賣家通過快遞(CDN服務(wù))寄送包裹,從北京到成都可以走路、坐汽車、火車或飛機,而采用CND的快遞會選擇飛機直達,因為這種寄送方式最快。

當(dāng)然使用CDN有兩個注意事項:

1、CDN加速服務(wù)很貴,如果你覺得你的網(wǎng)站值得加速,可以選擇購買;

2、CDN不適合局域性網(wǎng)站,比如你的網(wǎng)站只有某一個片區(qū)訪問或者局域網(wǎng)訪問,因為區(qū)域性網(wǎng)絡(luò)本來就很近,無需CDN加速。

--HTTP協(xié)議的合理使用

瀏覽器緩存帶來的性能提升已經(jīng)眾人皆知了,而很多人卻并不知道瀏覽器的緩存過期時間、緩存刪除、什么頁面可以緩存等,都可以由我們程序員來控制,只要您熟悉HTTP協(xié)議,就可以輕松的控制瀏覽器。

擴展閱讀:深入理解HTTP協(xié)議

--動靜分離

所謂的動靜分離,就是將Web應(yīng)用程序中靜態(tài)和動態(tài)的內(nèi)容分別放在不同的Web服務(wù)器上,有針對性的處理動態(tài)和靜態(tài)內(nèi)容,從而達到性能的提升。我們知道如果一個HTML有多個域名請求數(shù)據(jù)文件會提高

Tomcat服務(wù)器在處理靜態(tài)和并發(fā)問題上比較弱,所以事先動靜分離的方式一般會用Apache+Tomcat、Nginx+Tomcat等。

以Apache+Tomcat為例,其運行機理是:頁面請求首先給Apache,然后Apache分析請求信息是靜態(tài)還是動態(tài),靜態(tài)則本機處理,動態(tài)則交給Tomcat做處理。

這其實是負載均衡的雛形,這樣的實現(xiàn)不用讓開發(fā)人員做任何特殊開發(fā),一個<img src="demo.jpg">交給服務(wù)器即可,至于這個文件是從Apache還是從Tomcat取得,開發(fā)人員完全無需關(guān)注。

--HTTP持久連接

持久連接(Keep-Alive)也叫做長連接,它是一種TCP的連接方式,連接會被瀏覽器和服務(wù)器所緩存,在下次連接同一服務(wù)器時,緩存的連接被重新使用。HTTP無狀態(tài)性表示了它不屬于長連接,但HTTP/1.1提供了對長連接的支持(不過這必須依賴瀏覽器和服務(wù)器雙方均支持長連接功能才行),最常見的HTTP長連接例子是“斷點下載”。

瀏覽器在請求的頭部添加 Connection:Keep-Alive,以此告訴服務(wù)器“我支持長連接,你支持的話就和我建立長連接吧”,而倘若服務(wù)器的確支持長連接,那么就在響應(yīng)頭部添加“Connection:Keep-Alive”,從而告訴瀏覽器“我的確也支持,那我們建立長連接吧”。服務(wù)器還可以通過Keep-Alive:timeout=..., max=...的頭部告訴瀏覽器長連接失效時間。

配置長連接通常是要服務(wù)器支持設(shè)置,有測試數(shù)據(jù)顯示,使用長連接和不使用長連接的性能對比,對于Tomcat配置的maxKeepAliveRequests為50來說,效率竟然提升了將近5倍。

--GZIP壓縮技術(shù)

HTTP協(xié)議支持GZIP的壓縮格式,當(dāng)服務(wù)器返回的HTML信息報頭中包含Content-Encoding:gzip,它就告訴瀏覽器,這個響應(yīng)的返回數(shù)據(jù)已經(jīng)壓縮成GZIP格式,瀏覽器獲得數(shù)據(jù)后要進行解壓縮操作,一定程度上減輕了服務(wù)器傳輸數(shù)據(jù)的壓力。

很多服務(wù)器已經(jīng)支持通過配置來自動將HTML信息壓縮成GZIP,比如tomcat、又比如很火的Nginx。如果無法配置服務(wù)器級別的GZIP壓縮機制,可以改為程序壓縮。

 // 監(jiān)視對 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,才執(zhí)行壓縮,目的是測試用
 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 壓縮字節(jié)數(shù)組
 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(); 
 } 
……
 }
  • 總結(jié)

細節(jié)決定成敗,系統(tǒng)慢是由一個又一個不良的小細節(jié)造成的,所以開發(fā)初期做好充足的準備,開發(fā)中認真負責(zé)、不偷工減料,維護期更要注重代碼質(zhì)量,這樣才能讓我們的系統(tǒng)穩(wěn)定高效。

個人覺得一個產(chǎn)品的新版本質(zhì)量可以從核心js文件看出來:如果核心js文件大小比上一版本大太多,明顯在性能上就會有問題,我們要爭做像谷歌、亞馬遜這樣優(yōu)秀的團隊--能夠在功能升級的同時減小核心js文件大小。

以上就是關(guān)于HTML5中性能優(yōu)化的詳解的詳細內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!


網(wǎng)站建設(shè)是一個廣義的術(shù)語,涵蓋了許多不同的技能和學(xué)科中所使用的生產(chǎn)和維護的網(wǎng)站。