雅虎軍規——前端優化的35條建議

艾小莫的夢發表於2017-07-14

無論是在工作中,還是在面試中,web前端效能的優化都是很重要的,那麼我們進行優化需要從哪些方面入手呢?yohoo關於效能優化的35條的軍規,web2.0的設計與視覺,使用者越來越注重使用者體驗,但使用者體驗的前提就是網站的訪問速度,對於一個大型網站的yahoo來說,處理效能優化是不可缺少的,他是怎麼制定效能優化呢,相比很多朋友都想了解下,YaHoo把效能優化作為他們不可觸犯的軍規,具體怎樣優化呢,且看他們的優化方案。

80%-90%的終端響應時間是花費在下載頁面中的圖片,樣式表,指令碼,flash等;雅虎軍規可以分類7大類35條,包括內容、伺服器、CSS、JS、Cookie、圖片、移動應用。現在說一些常用的規則。

1、儘可能減少HTTP請求數

那麼什麼是HTTP請求呢?——從客戶端到伺服器端的請求訊息,包括訊息首行中,對資源的請求方法資源的識別符號及使用的協議。通俗一點說就是:當你開啟網頁的時候,你所看到的文字、圖片、多媒體等等,這一切內容,都是從伺服器獲取的。每一個內容的獲取,就是一個HTTP請求。

合併檔案:把所有的指令碼放到一個檔案中來減少HTTP請求。比如合併專案中的JS、CSS。

CSS Sprites是減少圖片請求數量的首選方式。把背景圖片都整合到一張圖片中,然後用CSS的background-image和background-position屬性來定位要顯示的部分。

減少頁面的HTTP請求數是個起點,這是提升站點首次訪問速度的重要指導原則。

瞭解這個只是對於我們網站設計和優化有何啟示呢?

  1. 由於DNS查詢是需要時間的,而且它們通常都是隻快取一定的時間,所以應該儘可能地減少DNS查詢的次數。

  2. 減少DNS查詢次數,最理想的方法就是將所有的內容資源都放在同一個域(Domain)下面,這樣訪問整個網站就只需要進行一次DNS查詢,這樣可以提高效能。

  3. 但理想總歸是理想,上面的理想做法會帶來另外一個問題,就是由於這些資源都在同一個域,而HTTP /1.1 中推薦客戶端針對每個域只有一定數量的並行度(它的建議是2),那麼就會出現下載資源時的排隊現象,這樣就會降低效能。

  4. 所以,折衷的做法是:建議在一個網站裡面使用至少2個域,但不多於4個域來提供資源。我認為這條建議是很合理的,也值得我們在專案實踐中去應用。

2、減少DNS查詢

域名系統建立了主機名和IP地址間的對映,就像電話簿上人名和號碼的對映一樣。當你在瀏覽器輸入www.yahoo.com的時候,瀏覽器就會聯絡DNS解析器返回伺服器的IP地址。DNS是有成本的,它需要20到120毫秒去查詢給定主機名的IP地址。在DNS查詢完成之前,瀏覽器無法從主機名下載任何東西。

大多數瀏覽器有獨立於作業系統的自己的cache。只要瀏覽器在自己的cache裡還保留著這條記錄,它就不會向作業系統查詢DNS。

IE預設快取DNS查詢30分鐘,寫在DnsCacheTimeout登錄檔設定中。Firefox快取1分鐘,可以用network.dnsCacheExpiration配置項設定。Chrome同樣快取一分鐘。

那麼時間長短有什麼不同呢?

快取時間長:減少DNS的重複查詢,節省時間

快取時間短:及時的檢測網站伺服器的變化,保證正確性。

3、避免重定向

重定向用301(永久性重定向)和302(臨時重定向)狀態碼,下面是一個有301狀態碼的HTTP頭:

HTTP/1.1 301 Moved Permanently
      Location: http://example.com/newuri
      Content-Type: text/html

牢記重定向會拖慢使用者體驗,在使用者和HTML文件之間插入重定向會延遲頁面上的所有東西,頁面無法渲染,元件也無法開始下載,直到HTML文件被送達瀏覽器。

有一種常見的極其浪費資源的重定向,而且web開發人員一般都意識不到這一點,就是URL尾部缺少一個斜線的時候。例如,跳轉到http://astrology.yahoo.com/astrology會返回一個重定向到http://astrology.yahoo.com/astrology/的301響應(注意添在尾部的斜線)。在Apache中可以用Alias,mod_rewrite或者DirectorySlash指令來取消不必要的重定向。

如果你的網站使用了301重定向,搜尋引擎在爬網的時候,會進行分析。當發現是301重定向的時候,它會記錄下新的地址,刪除原來的舊地址。也就是說301使得搜尋引擎變得智慧。

如果你使用的是302,搜尋引擎會先找到舊地址,再去跳新的地址。

4、使AJAX快取

利用時間戳,更精巧的實現響應可快取與伺服器資料同步更新。

5、為檔案頭指定Expires或Cache-Control,使內容具有快取性

區分靜態內容和動態內容,避免以後頁面訪問中不必要的HTTP請求。

6、使用CDN(內容分發網路)

這裡可以關注CDN的三類實現:映象、快取記憶體、專線,以及智慧路由器和負載均衡;

7、啟用Gzip壓縮

GZIP,即網頁壓縮,是由WEB伺服器和瀏覽器之間共同遵守的協議,也就是說WEB伺服器和瀏覽器都必須支援該技術,而現在主流的瀏覽器都是支 持的,包括IE、FireFox、谷歌瀏覽器、Opera 等。常見的WEB伺服器有Apache 和IIS 等。雙方的協商過程如下:

(1)首先瀏覽器請求某個URL 地址,並在請求的頭 (head) 中設定屬性accept-encoding值為gzip、deflate,表明瀏覽器支援gzip和deflate這兩種壓縮方式。

(2)WEB伺服器接收到請求後判斷瀏覽器是否支援壓縮,如果支援就傳送壓縮後的響應內容,否則傳送不經過壓縮的內容;

(3)瀏覽器獲取響應內容後,判斷內容是否被壓縮,如果是則解壓縮,然後顯示響應頁面的內容。

GZIP壓縮的比率往往在3到10倍,也就是本來90k大小的頁面,採用壓縮後實際傳輸的內容大小隻有28至30K大小,這可以大大節省伺服器的 網路頻寬,同時如果應用程式的響應足夠快時,網站的速度瓶頸就轉到了網路的傳輸速度上,因此內容壓縮後就可以大大的提升頁面的瀏覽速度。

在實際應用中,並不需要對網站所有檔案都進行壓縮,只需要對靜態檔案進行壓縮就可以了,包括js、css及html檔案。對其他檔案進行壓縮並不 會對WEB效能有太多的改觀,並且對網站開啟GZIP功能是需要犧牲部分伺服器效能的。

8、將css放在頁面最上面

關注效能的前端工程師想讓頁面逐步渲染。也就是說,我們想讓瀏覽器儘快顯示已有內容,這在頁面上有一大堆內容或者使用者網速很慢時顯得尤為重要。

9、將script放下頁面最下面

指令碼會阻塞並行下載,HTTP/1.1官方文件建議瀏覽器每個主機名下並行下載的元件數不要超過兩個,如果圖片來自多個主機名,並行下載的數量就可以超過兩個。如果指令碼正在下載,瀏覽器就不開始任何其它下載任務,即使是在不同主機名下的。

再比如,如果引入的js檔案有個死迴圈或者執行時間很長的指令碼,如果將這個指令碼放到頭部,那麼瀏覽器會一直載入這個指令碼而停止對網頁的渲染,會造成頁面一直空白,使用者一直等待渲染的問題。這將造成很差的使用者體驗。如果將此指令碼放到頁面最下面,頁面的HTML、CSS將先呈現給使用者,使用者會因為頁面提前載入而覺得速度更快。

有時候,並不容易把指令碼移動到底部。舉個例子,如果指令碼是用document.write插入到頁面內容中的,就沒辦法再往下移了。還可能存在作用域問題,在多數情況下,這些問題都是可以解決的。

一個常見的建議是用推遲(deferred)指令碼,有DEFER屬性的指令碼意味著不能含有document.write,並且提示瀏覽器告訴他們可以繼續渲染。不幸的是,Firefox不支援DEFER屬性。在IE中,指令碼可能被推遲,但不盡如人意。如果指令碼可以推遲,我們就可以把它放到頁面底部,頁面就可以更快地載入。

10、把JavaScript和CSS放到外面

很多效能原則都是關於如何管理外部元件的,然而,在這些顧慮出現之前你應該問一個更基礎的問題:應該把JavaScript和CSS放到外部檔案中還是直接寫在頁面裡?

實際上,用外部檔案可以讓頁面更快,因為JavaScript和CSS檔案會被快取在瀏覽器。HTML文件中的行內JavaScript和CSS在每次請求該HTML文件的時候都會重新下載。這樣做減少了所需的HTTP請求數,但增加了HTML文件的大小。另一方面,如果JavaScript和CSS在外部檔案中,並且已經被瀏覽器快取起來了,那麼我們就成功地把HTML文件變小了,而且還沒有增加HTTP請求數。

所以是否將這兩種檔案放到外面不是絕對的,應該視情況而定。如果這是一個不常訪問的頁面,或者這個頁面的css、js非常少,只有幾行,那麼完全沒有必要放到外面。

11、移除重複的指令碼

頁面含有重複的指令碼檔案會影響效能,這可能和你想象的不一樣。在對美國前10大web站點的評審中,發現只有2個站點含有重複指令碼。兩個主要原因增加了在單一頁面中出現重複指令碼的機率:團隊大小和指令碼數量。在這種情況下,重複指令碼會建立不必要的HTTP請求,執行無用的JavaScript程式碼,而影響頁面效能。

  IE會產生不必要的HTTP請求,而Firefox不會。在IE中,如果一個不可快取的外部指令碼被頁面引入了兩次,它會在頁面載入時產生兩個HTTP請求。即使指令碼是可快取的,在使用者重新載入頁面時也會產生額外的HTTP請求。

  除了產生沒有意義的HTTP請求之外,多次對指令碼求值也會浪費時間。因為無論指令碼是否可快取,在Firefox和IE中都會執行冗餘的JavaScript程式碼。

  避免不小心把相同指令碼引入兩次的一種方法就是在模版系統中實現指令碼管理模組。典型的指令碼引入方法就是在HTML頁面中用SCRIPT標籤:

<script type="text/javascript" src="menu_1.0.17.js"></script>

12、不要用HTML縮放圖片

不要因為在HTML中可以設定寬高而使用本不需要的大圖。如果需要

<img width="100" height="100" src="mycat.jpg" alt="My Cat" />

那麼圖片本身(mycat.jpg)應該是100x100px的,而不是去縮小500x500px的圖片。

13、減少cookie的大小

使用cookie的原因有很多,比如授權和個性化。HTTP頭中cookie資訊在web伺服器和瀏覽器之間交換。重要的是保證cookie儘可能的小,以最小化對使用者響應時間的影響。

  • 列表內容

去除不必要的coockie
使coockie體積儘量小以減少對使用者響應的影響
注意在適應級別的域名上設定coockie以便使子域名不受影響
設定合理的過期時間。較早地Expire時間和不要過早去清除coockie,都會改善使用者的響應時間。

14、避免圖片src屬性為空

Image with empty string src屬性是空字串的圖片很常見,主要以兩種形式出現:

straight HTML:

<img src=””>

JavaScript:

var img = new Image();
img.src = “”;

雅虎的團隊指出,如果你將img的src留空,可能你的本意是暫時不要顯示任何圖片,但在不同的瀏覽器其實還是會有一些額外的請求發生。據我的觀察,現在的這些瀏覽器都不再傳送額外的請求了。這也算是瀏覽器自身的改進吧,為什麼要對一個空白的img去發起額外的請求呢?

但既然以前早期的版本有可能發生這樣的事情,如果你無法確保你的使用者都使用最新的現代瀏覽器,那麼請簡單地遵守這條原則:總是給img的src設定值,而且是一個合法的值。

作為開發者,我理解有的時候,你想將src留空的原因在於,頁面載入的時候,你想快速完全載入,這些圖片你可能想後期再根據實際情況再載入。如果真的是這樣,你應該參考一下另外一個討論:優化網站設計(十七):延遲或按需載入內容。

或者很簡單地,你可以將初始圖片設定為一個很小的預設圖片(這個圖片設定永不過期),而不是留空。

相關文章