1.盡量減少HTTP請(qǐng)求數(shù)
80%的終端用戶響應(yīng)時(shí)間都花在了前端上,其中大部分時(shí)間都在下載頁面上的各種組件:圖片,樣式表,腳本,F(xiàn)lash等等。減少組件數(shù)必然能夠減少頁面提交的HTTP請(qǐng)求數(shù)。這是讓頁面更快的關(guān)鍵。
減少頁面組件數(shù)的一種方式是簡(jiǎn)化頁面設(shè)計(jì)。但有沒有一種方法可以在構(gòu)建復(fù)雜的頁面同時(shí)加快響應(yīng)時(shí)間呢?嗯,確實(shí)有魚和熊掌兼得的辦法。
合并文件是通過把所有腳本放在一個(gè)文件中的方式來減少請(qǐng)求數(shù)的,當(dāng)然,也可以合并所有的CSS。如果各個(gè)頁面的腳本和樣式不一樣的話,合并文件就是一項(xiàng)比較麻煩的工作了,但把這個(gè)作為站點(diǎn)發(fā)布過程的一部分確實(shí)可以提高響應(yīng)時(shí)間。
CSS Sprites是減少圖片請(qǐng)求數(shù)量的首選方式。把背景圖片都整合到一張圖片中,然后用CSS的background-image和background-position屬性來定位要顯示的部分。
圖像映射可以把多張圖片合并成單張圖片,總大小是一樣的,但減少了請(qǐng)求數(shù)并加速了頁面加載。圖片映射只有在圖像在頁面中連續(xù)的時(shí)候才有用,比如導(dǎo)航條。給image map設(shè)置坐標(biāo)的過程既無聊又容易出錯(cuò),用image map來做導(dǎo)航也不容易,所以不推薦用這種方式。
行內(nèi)圖片(Base64編碼)用data: URL模式來把圖片嵌入頁面。這樣會(huì)增加HTML文件的大小,把行內(nèi)圖片放在(緩存的)樣式表中是個(gè)好辦法,而且成功避免了頁面變“重”。但目前主流瀏覽器并不能很好地支持行內(nèi)圖片。
減少頁面的HTTP請(qǐng)求數(shù)是個(gè)起點(diǎn),這是提升站點(diǎn)首次訪問速度的重要指導(dǎo)原則。
2、減少DNS查找
DNS就像電話簿將人們的姓名映射到他們的電話號(hào)碼一樣,當(dāng)您輸入www.yahoo.com時(shí),瀏覽器會(huì)通過DNS解析返回服務(wù)器的IP地址,這個(gè)DNS解析過程需要成本,通常需要20-120ms才能解析成功,在這之前,瀏覽器無法從服務(wù)器獲取任何內(nèi)容。
通過緩存DNS查找來獲得更好的性能。DNS信息保留在操作系統(tǒng)的DNS緩存中,大多數(shù)的瀏覽器都有自己的緩存,與操作系統(tǒng)的分開。
默認(rèn)情況,IE會(huì)將DNS查找緩存30分鐘,F(xiàn)ireFox緩存一分鐘。
當(dāng)客戶端的DNS緩存為空(對(duì)于瀏覽器和操作系統(tǒng))時(shí),DNS查找的數(shù)量等于網(wǎng)頁中唯一主機(jī)名的數(shù)量。 減少唯一主機(jī)名的數(shù)量可減少DNS查找的數(shù)量。
減少唯一主機(jī)名的數(shù)量有可能減少頁面中發(fā)生的并行下載量。避免DNS查找會(huì)縮短響應(yīng)時(shí)間,但減少并行下載可能會(huì)縮短響應(yīng)時(shí)間。 準(zhǔn)則是將這些組件分成至少兩個(gè)但不超過四個(gè)主機(jī)名。這是減少DNS查找和允許高度并行下載之間的良好折衷。
3、讓Ajax可緩存
Ajax的一個(gè)好處是可以給用戶提供即時(shí)反饋,因?yàn)樗軌驈暮笈_(tái)服務(wù)器異步請(qǐng)求信息。然而,用了Ajax就無法保證用戶在等待異步JavaScript和XML響應(yīng)返回期間不會(huì)非常無聊。在很多應(yīng)用程序中,用戶能夠一直等待取決于如何使用Ajax。例如,在基于web的電子郵件客戶端中,用戶為了尋找符合他們搜索標(biāo)準(zhǔn)的郵件消息,將會(huì)保持對(duì)Ajax請(qǐng)求返回結(jié)果的關(guān)注。重要的是,要記得“異步”并不意味著“即時(shí)”。
要提高性能,優(yōu)化這些Ajax響應(yīng)至關(guān)重要。最重要的提高Ajax性能的方法就是讓響應(yīng)變得可緩存,就像在添上Expires或者Cache-Control HTTP頭中討論的一樣。下面適用于Ajax的其它規(guī)則:Gzip組件、減少DNS查找、壓縮JavaScript、避免重定向、配置ETags。
4、避免重定向
使用301和302狀態(tài)碼完成重定向。下面是一個(gè)301響應(yīng)http頭示例:
HTTP/1.1 301 Moved Permanently
Location: http://example.com/newuri
Content-Type: text/html
瀏覽器自動(dòng)將用戶帶到Location字段指定的URL。跳轉(zhuǎn)所需的所有信息都在http頭 ,響應(yīng)的主體通常是空的。301或302響應(yīng)一般不會(huì)被緩存,除非有Expires 或者Cache-Control 指定要緩存。
要記住的主要事情是重定向會(huì)降低用戶體驗(yàn)。在用戶和HTML文檔之間插入重定向會(huì)延遲頁面中的所有內(nèi)容,因?yàn)轫撁嬷械娜魏蝺?nèi)容都無法呈現(xiàn),并且在HTML文檔到達(dá)之前不會(huì)開始下載任何組件。
最浪費(fèi)的重定向之一經(jīng)常發(fā)生,就是在URL中缺少尾部/ 會(huì)產(chǎn)生301響應(yīng)
5、延遲加載組件
可以湊近看看頁面并問自己:什么才是一開始渲染頁面所必須的?其余內(nèi)容都可以等會(huì)兒。
JavaScript是分隔onload事件之前和之后的一個(gè)理想選擇。例如,如果有JavaScript代碼和支持拖放以及動(dòng)畫的庫,這些都可以先等會(huì)兒,因?yàn)橥戏旁厥窃陧撁孀畛蹁秩局蟮?。其它可以延遲加載的部分包括隱藏內(nèi)容(在某個(gè)交互動(dòng)作之后才出現(xiàn)的內(nèi)容)和折疊的圖片。
工具可幫你減輕工作量:YUI Image Loader可以延遲加載折疊的圖片,還有YUI Get utility是一種引入JS和CSS的簡(jiǎn)單方法。Yahoo!主頁就是一個(gè)例子,可以打開Firebug的網(wǎng)絡(luò)面板仔細(xì)看看。
最好讓性能目標(biāo)符合其它web開發(fā)最佳實(shí)踐,比如“漸進(jìn)增強(qiáng)”。如果客戶端支持JavaScript,可以提高用戶體驗(yàn),但必須確保頁面在不支持JavaScript時(shí)也能正常工作。所以,在確定頁面運(yùn)行正常之后,可以用一些延遲加載腳本增強(qiáng)它,以支持一些拖放和動(dòng)畫之類的華麗效果。
6、預(yù)加載組件
預(yù)加載看起來和延遲加載相反,但它實(shí)際上有著不同的目標(biāo),通過預(yù)加載組件,您可以利用瀏覽器空閑的時(shí)間并請(qǐng)求將來需要的組件(如圖像,樣式和腳本)。這樣,當(dāng)用戶訪問下一頁時(shí),您可以將大部分組件放在緩存中,并且用戶加載頁面將更快。
有幾種預(yù)加載類型:
無條件預(yù)加載:一旦onload觸發(fā),你立即獲取另外的組件。比如谷歌會(huì)在主頁這樣加載搜索結(jié)果頁面用到的雪碧圖。
有條件預(yù)加載:基于用戶操作,您可以進(jìn)行有根據(jù)的猜測(cè),即用戶前進(jìn)的位置并相應(yīng)地預(yù)加載。
預(yù)期的預(yù)加載:在舊網(wǎng)頁預(yù)加載新網(wǎng)頁的部分組件,那么切換到新網(wǎng)頁時(shí)就不會(huì)是沒有任何緩存了。
7、減少DOM數(shù)量
復(fù)雜頁面意味著要下載更多字節(jié),這也意味著JavaScript中的DOM訪問速度更慢。例如,當(dāng)您想要添加事件處理程序時(shí),如果在頁面上循環(huán)遍歷500或5000個(gè)DOM元素,則會(huì)有所不同。
8、跨域拆分組件
拆分組件來達(dá)到最大化的并行下載,由于DNS查詢的副作用,最好保證使用的域名不準(zhǔn)超過2-4個(gè)。例如,您可以托管HTML和動(dòng)態(tài)內(nèi)容,www.example.org 并在static1.example.org和之間拆分靜態(tài)組件。
9、 最少的iframe
iframe允許html文檔被插入到父文檔。
<iframe>優(yōu)點(diǎn):幫助解決緩慢的第三方內(nèi)容的加載,如廣告和徽章、安全沙盒、并行下載腳本
<iframe>缺點(diǎn):
即使空的也消耗(資源和時(shí)間)、阻塞了頁面的onload、非語義化(標(biāo)簽)
10、優(yōu)化圖片
嘗試把GIF格式轉(zhuǎn)換成PNG格式,看看是否節(jié)省空間。在所有的PNG圖片上運(yùn)行pngcrush(或者其它PNG優(yōu)化工具)
根據(jù)不同終端,切不同格式不同分辨率大小的圖,如png8 png24 gif jpg等(附加)
美工設(shè)計(jì),電腦端設(shè)計(jì)建議寬1920以上,移動(dòng)端以iphone6尺寸為基礎(chǔ)保證失真率最小 750畫布(附加)
根據(jù)不同屏幕大小。media query調(diào)用不同尺寸的圖片
11、把組件放在不含cookie的域下
當(dāng)瀏覽器發(fā)送對(duì)靜態(tài)圖像的請(qǐng)求時(shí),cookie也會(huì)一起發(fā)送,而服務(wù)器根本不需要這些cookie。所以它們只會(huì)造成沒有意義的網(wǎng)絡(luò)通信量,應(yīng)該確保對(duì)靜態(tài)組件的請(qǐng)求不含cookie??梢詣?chuàng)建一個(gè)子域,把所有的靜態(tài)組件都部署在那兒。
如果域名是www.example.org,可以把靜態(tài)組件部署到static.example.org。然而,如果已經(jīng)在頂級(jí)域example.org或者www.example.org設(shè)置了cookie,那么所有對(duì)static.example.org的請(qǐng)求都會(huì)含有這些cookie。這時(shí)候可以再買一個(gè)新域名,把所有的靜態(tài)組件部署上去,并保持這個(gè)新域名不含cookie。Yahoo!用的是yimg.com,YouTube是ytimg.com,Amazon是images-amazon.com等等。
把靜態(tài)組件部署在不含cookie的域下還有一個(gè)好處是有些代理可能會(huì)拒絕緩存帶cookie的組件。有一點(diǎn)需要注意:如果不知道應(yīng)該用example.org還是www.example.org作為主頁,可以考慮一下cookie的影響。省略www的話,就只能把cookie寫到*.example.org,所以因?yàn)樾阅茉蜃詈糜脀ww子域,并且把cookie寫到這個(gè)子域下。
12、跨域分離組件
分離組件可以最大化并行下載,但要確保只用不超過2-4個(gè)域,因?yàn)榇嬖贒NS查找的代價(jià)。例如,可以把HTML和動(dòng)態(tài)內(nèi)容部署在www.example.org,而把靜態(tài)組件分離到static1.example.org和static2.example.org。
13、把樣式表放在頂部
在Yahoo!研究性能的時(shí)候,我們發(fā)現(xiàn)把樣式表放到文檔的HEAD部分能讓頁面看起來加載地更快。這是因?yàn)榘褬邮奖矸旁趆ead里能讓頁面逐步渲染。
關(guān)注性能的前端工程師想讓頁面逐步渲染。也就是說,我們想讓瀏覽器盡快顯示已有內(nèi)容,這在頁面上有一大堆內(nèi)容或者用戶網(wǎng)速很慢時(shí)顯得尤為重要。給用戶顯示反饋(比如進(jìn)度指標(biāo))的重要性已經(jīng)被廣泛研究過,并且被記錄下來了。在我們的例子中,HTML頁面就是進(jìn)度指標(biāo)!當(dāng)瀏覽器逐漸加載頁面頭部,導(dǎo)航條,頂部logo等等內(nèi)容的時(shí)候,這些都被正在等待頁面加載的用戶當(dāng)作反饋,能夠提高整體用戶體驗(yàn)。
14、保持組件小于25K
此限制與iPhone不會(huì)緩存大于25K的組件這一事實(shí)有關(guān)。請(qǐng)注意,這是未壓縮的大小。在這里減少組件大小很重要,因?yàn)閱为?dú)使用gzip可能還不夠。
15、將組件打包到多部分文檔中
將組件打包到多部分文檔就像帶有附件的電子郵件,它可以幫助您通過一個(gè)HTTP請(qǐng)求獲取多個(gè)組件(請(qǐng)記住:HTTP請(qǐng)求很昂貴)。使用此技術(shù)時(shí),首先檢查用戶代理是否支持它(iPhone不支持)。