高性能网站建设的最佳实践(二)
原文譯自雅虎開發(fā)者社區(qū),轉(zhuǎn)載譯文請(qǐng)標(biāo)明出處。
關(guān)注我的sina微博,共同進(jìn)步!
為了讓網(wǎng)頁響應(yīng)速度更快Exceptional Performance團(tuán)隊(duì)列出了一系列的最佳實(shí)踐,包括35個(gè)最佳實(shí)踐條目,分成7種類型類。
避免重定向
標(biāo)簽:內(nèi)容
使用301和302狀態(tài)碼可以完成重定向。這里有個(gè)301響應(yīng)的HTTP報(bào)文頭部實(shí)例:
HTTP/1.1 301 MovedPermanently
Location: http://example.com/newuri
Content-Type: text/html
瀏覽器自動(dòng)的將用戶引導(dǎo)到location字段所指定的URL地址。所有的重定向的必要信息都位于報(bào)文頭部,報(bào)文體通常為空。301和302響應(yīng)并不被緩存除非添加像Expires或者Cache-Controll的報(bào)文頭部以指定瀏覽器需要進(jìn)行緩存。Meta刷新標(biāo)簽和JavaScript是其他的將用戶引導(dǎo)到不同URL地址的方法,但是如果你必須重定向,更好的方式是使用3xx的HTTP狀態(tài)碼,這樣可以確保瀏覽器返回按鈕工作正常。
需要關(guān)注的是重定向減慢了用戶的體驗(yàn)。將重定向插入到用戶和HTML文件中會(huì)減慢頁面中的一切,這是由于直到HTML文檔完成加載,頁面中沒有可以被渲染的東西也沒有組件開始被渲染。
一個(gè)經(jīng)常發(fā)生的耗費(fèi)的重定向并且卻通常會(huì)被開發(fā)者疏忽的問題如下。URL地址末尾本該有的斜線丟失時(shí)就會(huì)出現(xiàn)這種問題,例如,訪問http://astology.yahoo.com/astrology 會(huì)導(dǎo)致301響應(yīng)的發(fā)生,將頁面重定向到http://astology.yahoo.com/astrology/(注意添加了斜線)。在Apache中通過使用Alias或者mod_rewrite或者DirectorySlash來修正。
連接遺留網(wǎng)站到一個(gè)新的網(wǎng)站是重定向的另一個(gè)應(yīng)用。其他的情況包括連接網(wǎng)站中不同的部分和基于特定的條件(瀏覽器類型,用戶賬戶)將用戶引導(dǎo)開。使用重定向來連接兩個(gè)網(wǎng)站是件容易的事并且需要很少的額外編碼。盡管在這些情況下使用重定向減少了開發(fā)者的工作量,這也降低了用戶的體驗(yàn)??蛇x的方式是當(dāng)兩套編碼位于同一個(gè)服務(wù)器上時(shí),使用Alias和mod_rewrite來完成重定向。如果是因?yàn)?/span>域名更改而需要重定向,一個(gè)可選的方法是創(chuàng)建CNAME記錄(創(chuàng)建別名從一個(gè)域名指向另一個(gè)域名的DNS記錄)結(jié)合Alias和mod_rewrite來實(shí)現(xiàn)。
移除重復(fù)的腳本文件
標(biāo)簽:JavaScript
在一個(gè)頁面中包含同樣的JavaScript代碼兩次會(huì)降低性能。你想這種事情可能并不常發(fā)生。在對(duì)美國前十的網(wǎng)站的一個(gè)檢查是發(fā)現(xiàn)他們中的兩個(gè)包含重復(fù)的腳本文件。兩個(gè)主要的因素增加了單頁面中腳本文件重復(fù)的偶然性:團(tuán)隊(duì)規(guī)模和腳本文件的個(gè)數(shù)。當(dāng)這樣的是發(fā)生時(shí),重復(fù)的腳本元素通過創(chuàng)建不必要的HTTP請(qǐng)求以及浪費(fèi)JavaScript的執(zhí)行資源來降低性能。
不必要的HTTP請(qǐng)求會(huì)在IE中發(fā)生,然而在Firefox中卻沒有。在IE中,如果外聯(lián)的腳本文件被包含兩次并且未被緩存,IE就在頁面渲染的過程中產(chǎn)生兩個(gè)HTTP請(qǐng)求。即使腳本文件被緩存了,額外的HTTP請(qǐng)求在頁面重新加載的過程中也會(huì)發(fā)生。
除了產(chǎn)生不必要的HTTP請(qǐng)求,腳本的多次執(zhí)行也浪費(fèi)了時(shí)間。多余的JavaScript執(zhí)行會(huì)在IE和Firefox中同時(shí)發(fā)生,而不管是否緩存。
一個(gè)避免意外的包含兩次同樣的腳本的方法是實(shí)現(xiàn)你的模板系統(tǒng)中的腳本管理模塊。典型的方法是在HTML頁面中使用Script標(biāo)簽。
<script type=”text/javascript”src=”menu.js”></script>
在PHP中可以借助于調(diào)用insertScript函數(shù)來實(shí)現(xiàn)
<?php insertScript(“menu.js”)?>
除了防止同腳本文件被插入兩次,這個(gè)函數(shù)可以處理其他的腳本問題,比如依賴檢查以及為腳本的文件名中添加版本號(hào)以支持長時(shí)間過期的頭部(ExpiresHeader)。
配置ETags
標(biāo)簽:服務(wù)器端
實(shí)體標(biāo)簽(ETags)是web服務(wù)器和瀏覽器用來判斷緩存中的組件和源服務(wù)器中的組件是否匹配的機(jī)制。(“entity”是“component”的另一種表述:圖像,腳本,樣式等)ETags通過提供比last-modified日期更富有彈性的機(jī)制來驗(yàn)證實(shí)體。一個(gè)Etag就是一個(gè)唯一標(biāo)示一個(gè)組件版本的字符串。唯一的格式限制是這個(gè)字符串必須使用引號(hào)來標(biāo)注。源服務(wù)器通過ETag響應(yīng)報(bào)文頭部來指定組件的ETag。
HTTP/1.1 200 Ok
Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT
ETag: “10c24bc-4ab-457e1c1f”
Content-Length: 12195
稍后,如果瀏覽器不得不驗(yàn)證組件,將使用If-None-Match頭部將ETag傳回到源服務(wù)器。如ETag匹配,304狀態(tài)碼將會(huì)被返回也就減少了響應(yīng)報(bào)文12195字節(jié)。
GET /i/yahoo.git HTTP/1.1
Host: us.yimg.com
If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT
If-None-match: “10c24bc-4ab-457e1c1f”
HTTP/1.1 304 Not Modified
ETags的問題在于它們使用特殊屬性來構(gòu)建,使得它們只對(duì)應(yīng)于一個(gè)特定的服務(wù)器。當(dāng)從一個(gè)服務(wù)器上得到一個(gè)源組件稍后又從另一個(gè)不同的服務(wù)器上去驗(yàn)證的情況下,ETag是不會(huì)匹配的,這種情況在使用服務(wù)器集群處理請(qǐng)求的Web站點(diǎn)中是很普遍的現(xiàn)象。默認(rèn)情況下,Apache和IIS都為ETag嵌入了數(shù)據(jù)奇跡般的較少了驗(yàn)證過程中的奇怪特性,這在基于多個(gè)服務(wù)器上的web站點(diǎn)上測試可行。
Apache1.3和2.x上ETag格式是inode-size-timestamp,盡管在多個(gè)服務(wù)器上會(huì)處于同一個(gè)目錄下、有著同樣的尺寸、許可、時(shí)間戳等。inode卻隨著不同的服務(wù)器而不同。
II5.0和6.0在ETags上有相似的問題。ETags在IIS上的格式是:Filetimestamp:ChangeNumber。“ChangeNumber”是用于記錄對(duì)IIS的配置改變。在一個(gè)Web站點(diǎn)的所有的IIS服務(wù)器上,ChangeNumber一般是不同的。
結(jié)果就是由Apache和IIS為一個(gè)相同的模塊產(chǎn)生的ETags在不同的服務(wù)器上并不匹配。如果ETags不匹配,用戶也就不會(huì)獲得簡短快速的304響應(yīng),而那恰恰是ETags被設(shè)計(jì)出目的;取而代之的是他們將會(huì)獲取一個(gè)正常的200響應(yīng),這個(gè)響應(yīng)攜帶了所有的組件數(shù)據(jù)。如果你僅僅在一個(gè)服務(wù)器上管理你的站點(diǎn),這不是問題。但是如果你有多個(gè)服務(wù)器來管理站點(diǎn),并且使用Apache和IIS的默認(rèn)ETag配置,你的用戶就獲得了更慢的頁面加載,你的服務(wù)器負(fù)荷也會(huì)加重,你浪費(fèi)了更多的帶寬,并且代理也不會(huì)很好的緩存你的內(nèi)容。即使你的組件有長時(shí)間過期的頭部,一個(gè)有條件GET請(qǐng)求也會(huì)發(fā)出無論用戶是點(diǎn)擊了重新加載或者刷新按鈕。
如果你沒有利用ETags所提供的所有的彈性驗(yàn)證模型,最好直接移除ETag機(jī)制。Last-Modified頭部依據(jù)組件的時(shí)間戳來驗(yàn)證。移除ETag會(huì)在相應(yīng)報(bào)文和后續(xù)的請(qǐng)求中減少了HTTP頭部的大小。這篇MicrosoftSupport文章介紹了如何移除ETags。在Apache中,在配置文件中僅僅加入下面這句話就能移除ETags:
FileETag:none
讓Ajax請(qǐng)求可被緩存
標(biāo)簽:內(nèi)容
Ajax的一個(gè)廣為人知的好處就是它為用戶提供了即時(shí)的反饋,因?yàn)樗惒降膹暮蠖朔?wù)器上加載信息。然而使用Ajax可能使得用戶為了等待異步的JavaScript和XML響應(yīng)而開始把玩他的大拇指,用戶是否一直等待取決于Ajax如何被使用。例如,在一個(gè)基于Web的郵件客戶端中,用戶一直等待Ajax的請(qǐng)求結(jié)果從而找到他們想要查詢的Email信息。記住異步并不意味著實(shí)時(shí)。
為了提升性能,優(yōu)化Ajax的響應(yīng)至關(guān)重要。最重要的一個(gè)途徑是將請(qǐng)求結(jié)果緩存起來,就像在“添加Expires和Cache-Contoll”一節(jié)中討論的那樣。一些其他的規(guī)則也適用于Ajax:
Gzip壓縮組件
減少DNS查詢
壓縮JavaScript
避免重定向
配置ETags
讓我們看看一個(gè)例子。一個(gè)Web2.0的郵件客戶端或許自動(dòng)使用Ajax來加載用戶的地址簿。如果自從上次使用email web程序以來,用戶沒有改變地址簿,之前的地址簿響應(yīng)數(shù)據(jù)可以從緩存中讀取,前提是Ajax緩存通過使用Expires或者Cache-Contolle頭部實(shí)現(xiàn)。瀏覽器必須被通知什么時(shí)候使用之前的緩存地址簿數(shù)據(jù)或者請(qǐng)求新的數(shù)據(jù)。這可以通過為地址簿的Ajax地址添加時(shí)間戳來標(biāo)注最后一次用戶更改地址簿的時(shí)間,從而實(shí)現(xiàn)上述目的,例如&t=1190241612。如果地址簿自從上一次加載以來沒有被改變,時(shí)間戳不變,瀏覽器會(huì)從緩存中獲取地址簿數(shù)據(jù)從而減少了一個(gè)HTTP往返請(qǐng)求。如果用戶改變了地址簿數(shù)據(jù),時(shí)間戳確保一個(gè)新的URL地址和緩存中的響應(yīng)不同,瀏覽器就向更新的地址簿入口請(qǐng)求數(shù)據(jù)。
盡管Ajax響應(yīng)報(bào)文被動(dòng)態(tài)的創(chuàng)建,但僅僅對(duì)單戶起作用,他們可以被緩存。這將使你的Web2.0應(yīng)用的更快。
盡早的清除緩存
標(biāo)簽:服務(wù)器端
當(dāng)用戶請(qǐng)求頁面,無論如何需要200-500ms的時(shí)間讓后端服務(wù)器生成一個(gè)頁面。在這個(gè)時(shí)間內(nèi),瀏覽器因?yàn)榈却龜?shù)據(jù)的到大而處于空閑的狀態(tài)。在PHP中有flush函數(shù)。它能夠?qū)⒉糠譁?zhǔn)備好了的HTML響應(yīng)發(fā)送給瀏覽器,使得瀏覽器可以開始加載組件而你的后端服務(wù)器忙于生成其他的HTML頁面。在忙碌的后端和松閑中都可以看到這樣做的好處。
一個(gè)添加好的flushing的地方就在HEAD標(biāo)簽后,因?yàn)?/span>html的Head標(biāo)簽通常容易生成,并且允許包好任何的CSS和JavaScript文件,這樣瀏覽器開始并行請(qǐng)求數(shù)據(jù)而后端仍然在處理其他的東西。
例如:
…<!—css, js-->
</head>
<?php flush();?>
<body>
…<!—content-->
Yahoo! Search主導(dǎo)了這方面研究并且在真實(shí)的用戶上進(jìn)行測試,從而證明使用這項(xiàng)技術(shù)的好處。
用GET發(fā)送AJAX請(qǐng)求
標(biāo)簽:服務(wù)器端
Yahoo!Mail團(tuán)隊(duì)發(fā)現(xiàn)當(dāng)使用XMLHttpRequest時(shí),POST在瀏覽器中經(jīng)歷了兩個(gè)步驟的處理:先發(fā)送請(qǐng)求頭部,然后發(fā)送數(shù)據(jù)。所以最好使用GET,僅僅使用一個(gè)TCP數(shù)據(jù)包發(fā)送請(qǐng)求(除非你有很多的cookies)。在IE中最大URL長度是2K,如果發(fā)送多于2K的數(shù)據(jù),你就不能使用GET。
一個(gè)讓人感興趣的個(gè)例是POST如果沒有發(fā)送任何數(shù)據(jù)的時(shí)候的行為類似于GET?;?/span>HTTP的規(guī)范,GET為的是獲取信息,所以在僅僅只是請(qǐng)求數(shù)據(jù)的時(shí)候使用GET是有意義的(從語義上),而和向服務(wù)器端發(fā)送數(shù)據(jù)則不同。
延遲加載模塊
標(biāo)簽:內(nèi)容
你可以仔細(xì)看下你的頁面,問問自己:“為了完成頁面的起始渲染,哪些是絕對(duì)需要的?”其余的內(nèi)容和組件可以稍后加載。
JavaScript是很適合置于onload事件觸發(fā)之前或之后。例如,如果你使用JavaScript或者庫來完成拖動(dòng)和動(dòng)畫的任務(wù),這些可以等待。因?yàn)樵陧撁嫔贤蟿?dòng)元素在初始渲染之后才可用。其他的可以在加載事件之后獲取的包括隱藏的內(nèi)容(在用戶的某個(gè)操作后出現(xiàn)的內(nèi)容)或者圖片折疊。
有些工具可以幫助你達(dá)成目的:YUI Image Loader允許你延遲加載位于折疊區(qū)域之后的圖片并且YUIGet Utility是一個(gè)簡單的方法來實(shí)時(shí)加載JS和CSS。例如可以使用Firebug面板看看Yahoo!Home Page的加載狀況。
當(dāng)性能目標(biāo)和其他的web開發(fā)最佳實(shí)踐相關(guān)聯(lián)時(shí)。這種情況下,漸進(jìn)增強(qiáng)的方法告訴我們JavaScript可以提升用戶體驗(yàn),但是你不得不確認(rèn)頁面在沒有JavaScript的情況下也是可用的。所以當(dāng)你確認(rèn)頁面工作良好,你可以通過一些后加載的腳本提升頁面,隨后當(dāng)你的拖動(dòng)效果和動(dòng)畫效果發(fā)揮效應(yīng)時(shí)會(huì)給你帶來跟多的喝彩。
繼續(xù)閱讀:高性能網(wǎng)站建設(shè)的最佳實(shí)踐(三)
原文譯自:http://developer.yahoo.com/performance/rules.html
轉(zhuǎn)載于:https://blog.51cto.com/moviejs/1305404
總結(jié)
以上是生活随笔為你收集整理的高性能网站建设的最佳实践(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在Excel表数据中快速创建新增脚本
- 下一篇: java jespa_Jespa实际运用