高性能網站建設指南總結

高性能網站建設指南總結

本文根據《高性能網站建設指南》一書進行總結,加上本身的理解和新的知識點進行補充添加。javascript

規則1——減小HTTP請求

只有10%到20%的最終用戶響應時間花在接收請求的HTML文檔上面。剩下80%到90%的 時間花在爲HTML文檔所引用的全部組件(圖片,腳本,flash,樣式表等)進行的HTTP請求上。所以改善響應的最簡單途徑就是減小組件數量,由此減小HTTP請求的數量。php

圖片地圖

使用map標籤進行座標定位,減小圖片數量。導航欄中使用了多個圖片時候可使用。
缺點不少:手工方式很難完成座標定位,且容易出錯。除了矩形以外也難以定義其餘形狀,經過DHTML定義的圖片IE中還沒法工做。不建議使用。css

CSS Sprites (雪碧圖/精靈圖)

經過把多個圖片合併到一個圖片,而後利用background-position進行定位,比使用分離圖片快50%。圖片地圖中的圖片必須是連續的,而CSS Sprites則沒有這個限制。也有人認爲合併後的圖片比分離的圖片總和還要大,合併後的圖片包含附加的空白區域。實際是變小的,雪碧圖下降了圖片自身的開銷。(顏色表,格式信息,等等)
若是頁面中背景,按鈕,導航欄,連接須要使用不少圖片,可使用。優勢——乾淨的標籤,不多的圖片和很短的響應時間。html

缺點:後期修改麻煩,難以維護,牽一髮動全身,沒有以前改一個圖片就行了容易前端

雪碧圖製做方法:java

  1. 百度搜索CSS Sprites 可找到相應制做軟件軟件下載地址
  2. gulp等自動化工具,自動合成
  3. ps本身製做

內聯圖片

使用 data:URL的模式在WEB頁面中包含圖片,但無需任何額外的HTTP請求。咱們都熟悉http:模式的URL。其餘相似模式包括ftp:,file:和maito:webpack

data:url模式

在1995年提出來:容許將小數據塊內聯爲當即數,數據就在url自身中。web

什麼是內聯圖片

內聯圖片是一種新型的圖像格式(在我看來是這樣不知道理解對否),官方稱爲:data URI scheme。一般咱們存儲的圖片在網頁中須要寫:ajax

<img src="http://blog.xmaoseo.com/images/xmaoseo.jpg"/>

而內聯圖片寫法會是express

<img src="data:image/png;base64,iVAGRw0KGDCFGNSUhEUgACBBQAVGADCAIATYJ7ljmRGGAAGElEVQQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPACCCTElFTEVBQmGA"/>

內聯圖片語法

<img src="data:image/png;base64,iVBOR....>
  1. data - 取得數據的協定名稱
  2. image/png - 數據類型名稱
  3. base64 - 數據的編碼方法
  4. iUANR.... - 編碼後的數據
  5. : , ; - data URI scheme 指定的分隔符號

這種圖片格式無需額外的HTTP請求是不錯,可是還有一個重要的一點,瀏覽器不會緩存這種圖像。 data url 節省了HTTP請求,可是若是這個圖像在網頁多個地方顯示會加大網頁的內容,延長下載時間。還有一點 IE8 如下都不支持這種圖像,因此仍是IE6的用戶就比較悲催了。而且超過 100kb 圖像使用base64編碼也會增大圖片大小。致使網頁總體下載量增長。 (BASE64編碼圖片致使網站瀏覽緩慢崩潰http://blog.xmaoseo.com/125.h... 可是不少聰明人作法是把背景平鋪類圖片做爲內聯圖片使用,這樣效果很不錯。也減小了HTTP請求加快了網站速度。那麼你可能會問到如何獲取圖片的base64編碼呢。網絡上有不少免費的base編碼和解碼工具,可是有個最簡單方法就是咱們寫一個PHP文件。使用base64_encode()進行編碼:好比:

echo base64_encode(file_get_contents('211-11.JPG'));

如何解決網頁下載延遲問題。最簡單一個方法就是用寫成CSS裏的背景去調用CLASS 類名就能夠了。好比我們用上面的例子:

.blogxmao{background:url(data:image/png;base64,iVAGRw0KGDCFGNSUhEUgACBBQAVGADCAIATYJ7ljmRGGAAGElEVQQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPACCCTElFTEVBQmGA")}
<div>..內容...</div><div>..內容...</div>

合併腳本和樣式表

根據模塊化原則, 咱們應該將代碼放到多個小文件中,可是這樣會下降性能,由於每一個文件都會致使一個額外的http請求。理想狀況,一個頁面不該該使用多餘一個的腳本和樣式表。世界前十網站腳本和樣式表通常不超過2個。
使用模塊化工具,好比seajs,requirejs進行優化。否則隨着文件的增多,手動合併將會很麻煩。

規則2——使用內容分發網絡 CDN

內容分發網絡(conten delivery network)是一組分佈在多個不一樣地理位置的Web服務器。可使用CDN服務提供商。

CDN優勢:

縮短相應時間,備份擴展存儲能力和進行緩存,緩和WEB流量峯值壓力(獲取天氣,娛樂體育新聞等等)

CDN缺點:

你的響應時間會受到其餘網站——甚至是競爭對手的流量的影響。沒法控制組件服務器所帶來的特殊麻煩。好比,修改HHTP表頭必須由服務提供商來完成。

若是CDN服務性能降低了,你的工做也會受到影響。固然你可使用兩個CDN服務提供商。

CDN用於發佈靜態圖片(將全部靜態組件轉移到CDN),圖片,腳本樣式表,Flash,靜態文件更易存儲,有較少的依賴性。

規則3——添加Expires頭

Web頁面包含大量組件,首次訪問時間並非惟一須要考慮的,頁面的初訪者會進行不少HTTP請求,可是可使用一個長久的Expires頭,使得這些組件被緩存

Expires頭

長久的expires常常用於圖片,然而能夠用於全部組件,不少頂級網站並無作到這一點,由於添加長久的ecpires頭會帶來額外的開發成本。

Expires:Mon,15 Apr 2025 00:00:00 GMT

它會告訴瀏覽器該響應的有效性會持續到2025年。

Max-Age 和mod_expires

由於expires使用一個特定的時間,要求客戶端和服務器端時鐘嚴格同步,過時日期須要檢查,還要配置新的日期,因此使用麻煩。HTTP1.1引入了Cache-Control頭來克服它的限制。Cache-Control使用max-age指令來指定組件被緩存多久。以秒爲單位定義了一個更 新窗。
對於不支持HTTP1.1的瀏覽器,你能夠同時指定兩個響應頭——Expiresmax-age.若是二者同時出現,後者將會重寫前者。若是你很盡責,你仍然會擔憂Expires過時問題以及時鐘同步問題。

幸運的是,mod_expires使你經過ExpirsDefault指令以相對方式設置日期。

ExpirsDefault 'access plus 10 years'

時間能夠設置爲年月日時分秒。它同時向響應中發送Expires頭和max-age頭。實際過時日期根據什麼時候獲得請求而變,可是max-age有優先權。時鐘同步問題和固定日期更新不用擔憂了。

跨瀏覽器改善緩存最佳方案就是使用 ExpirsDefault設置的Expires.

空緩存vs完整緩存

用戶第一次訪問你的網站它不會對HTTP的請求的數量產生任何影響。此時瀏覽器的緩存是空的。性能改進取決因而否有完整緩存。

在那些每日一次一更新的網站,帶有完整緩存的頁面瀏覽百分比不多。
旅遊網站,email網站中每一個用戶會話可能產生屢次頁面瀏覽,百分比就高。

只要用戶每月至少訪問一次,或者每次會話產生屢次頁面瀏覽,完整緩存就頗有用,使用長久Expires就頗有必要。

不只僅是圖片

腳本,樣式表,flash均可以緩存,可是HTML文檔不該該使用,由於包含動態內容,每次都要更新。
大型網站,圖片,樣式表,腳本大部分都要緩存30天以上。可是常常須要變化的新聞圖片等等,不該該使用。咱們能夠查看Last-Modifed中的值來看改變時間以及頻率。

修訂文件名

使用長久的Expires缺點是 :瀏覽器不會檢查任何更新,直到過了過時日期。即便在服務器上更新了組件,瀏覽器由於緩存也不能得到最新組件。

爲了確保用戶能得到更新過的組件,須要在全部HTML頁面中修改組件的文件名。

最有效的解決方案是修改其全部連接,這樣。全新的請求將從原始服務器下載最新的內容。

使用php等動態語言生成HTML頁將很簡單,爲全部組件的文件名使用變量,使用這種方法,在頁面中更新文件名只須要簡單地在某個地方修改變量。Yahoo常常將這一步做爲生成過程的一部分——版本號嵌入在組件的文件名中(例如yahoo_2.0.6.js),並且在全局映射中修訂過的文件名會自動更新。嵌入版本號不只能夠改變文件名,還能在調試中更容易找到準確的源代碼文件。

規則4——壓縮組件

規則1--3都是限制沒必要要的HTTP請求來減小響應時間,如今咱們經過減小響應大小來減小響應時間。

壓縮是如何工做的

用於減少文件體積的文件壓縮已經在email應用和ftp站點中使用了十年,一樣的技術也能夠用於向瀏覽器發佈壓縮的web頁面。

從HTTP1.1開始,web客戶端能夠經過請求中的Accept-Encoding頭來表示對文件壓縮的支持。


————>
Accept-Encoding:gzip

若是web服務器看到請求中有這個頭,就會使用客戶端列出來的方法中的一種來壓縮響應。並經過響應中的Content-Ecoding來通知客戶端。

<————
Content-Ecoding:gzip

gzip是目前最有效,最流行的壓縮方法,免費模式,並被標準化爲RFC 1952.(90%使用)

壓縮什麼

不少網站會壓縮HTML文檔,壓縮腳本和樣式表也是很是值得的,還包括XML和JSON在內的任何文本響應。圖片PDF不該該解壓縮,由於已經被壓縮了。再壓縮只會浪費CPU資源,還有可能會增長文件大小。

壓縮的成本:服務器會花費額外的CPU週期來完成壓縮,客戶端要對壓縮文件進行解壓縮。要檢測受益是否大於開銷,須要考慮響應的大小,鏈接的帶寬和和客戶端服務器之間的Internet距離。

根據經驗,一般對大於1KB或2KB的文件進行壓縮。mod_gzip_minimum_file_size指令控制着但願壓縮文件的最小值,默認值是500B。

美國十大流行網站中9個壓縮了html,七個壓縮了大多數腳本和樣式表,只要五個壓縮了全部腳本和樣式表。這能夠將頁面減小70%。

節省

壓縮以後能將響應總體減小60%左右

配置

配置gzip時使用的模塊取決於Apache(intert上最流行的web服務器,份額70%以上)的版本。Apache1.3使用mod_gzip,2.3使用mod_deflate.

具體配置詳情如何壓縮,壓縮哪些文件,壓縮程度,類型(可以使用正則匹配)可搜索mod_gzip的網站參考。

規則5——將樣式表放在頂部

使用link標籤將樣式表放在文檔head中

白屏

將css放在底部的時候(有觀點以爲DHTML特性東西在最後展示,因此會把css放在底部以爲更優化。)實則否則,這樣容易發生白屏和無樣式內容的閃爍。

DHTML不是 W3C 標準
DHTML 指動態 HTML(Dynamic HTML)。
DHTML 是一個營銷術語 - 被網景公司(Netscape)和微軟公司用來描述 4.x 代瀏覽器應當支持的新技術。
DHTML 是一種用來建立動態站點的技術組合物。
對大多數人來講,DHTML 意味着 HTML 4.0、樣式表以及 JavaScript 的結合物。

W3C 曾講過:「動態HTML是一個被某些廠商用來描述可以使文檔動態性更強的HTML、樣式表以及腳本的結合物的術語。」

好比一些打字機效果文字,閃爍文字,遮罩濾鏡等等。

白屏容易產生的地方,特別是在IE中:

  1. 新窗口中打開時
  2. 從新加載時
  3. 做爲主頁(打開新的瀏覽器窗口)

無樣式內容的閃爍FOUC

FOUC flash of unstyles content 產生緣由是沒有吧樣式表放在head頂部,或者使用了@import導入(即使放在前面了,樣式表仍是會最後下載)

因此避免無樣式內容閃爍最好方法就是使用link標籤將其放在head頂部

規則6——將腳本放在底部

腳本放在頂部會阻塞後面內容的呈現和組件的下載。進而產生白屏現象。
放在底部將會產生最小影響和最佳效應。

規則7——避免css表達式

css表達式 expression方法被其餘瀏覽器忽略,IE支持,這種方法雖然強大可是很是危險。

表達式求之的頻率遠高於人們的指望,不只在頁面呈現和大小改變時求值,鼠標拖拽,頁面滾動時候都會求值。因此要避開css表達式,用事件處理器來爲特定的事件提供所指望的動態行爲。

規則8—— 使用外部的js和css

**內聯VS外置**
單純比較而言,內聯在第一次加載時要快一點,由於內聯只有一個http請求。
可是多方面考慮仍是要用外置。
內聯沒法緩存,外置能夠緩存,並且當你頁面使用了相同的js和css時候,能夠組件重用,緩存優點更明顯。

最重要的是,外置能夠下降耦合度,調試更加方便~~~

規則9——減小DNS查找

Internet經過IP地址查找服務器,瀏覽器查找一個給定主機名的IP地址要花費20—120毫秒,也是有開銷的,充當這個角色的就是DNS(domain name system)

如何減小DNS查找

使用較少的域名,谷歌只有一個,由於只有兩個組件,能夠一次並行下載完,兩個主機是最好的,平衡並行下載和DNS查詢。
在HTTP請求中使用 Connection:keep-alive 來保持持久鏈接。早期HTTP請求中。每一個請求都要打開一個socket鏈接,由於頁面中不少請求收拾指向同一個服務器,因此這樣效率很低。持久鏈接的引入使得瀏覽器能夠在一個單獨的鏈接上進行多個請求。

HTTP1.1中定義的管道能夠在一個單獨的socket上發送多個請求而無需等待響應,並且性能優於持久鏈接。

規則10——精簡javascript

精簡

精簡是從代碼中移除沒必要要的字符以減少其大小。進而改善加載時間的實踐。

代碼精簡以後全部的註釋以及沒必要要的空白字符(空格,換行,製表符),能夠減少20%。

混淆

混淆是能夠應用在源代碼上的另一種優化方式,和精簡同樣,也會移除註釋和空白,做爲改寫的一部分,函數和變量的名字將被轉換爲更短的字符串。

這樣的代碼更加精煉,可是更難閱讀。一般這樣作是爲了增長對代碼進行反向工程的難度,但對提升性能也有幫助。

混淆js的三個缺點

  1. 缺陷:混淆更加複雜,混淆過程自己頗有可能引入錯誤。
  2. 維護: 因爲混淆會改變js符號,所以須要對任何不能改變的符號(例如API函數)進行標記,防止混淆修改他們。
  3. 調試:很難閱讀,調試更加困難。

精簡歷來不會帶來問題,可是混淆會帶來不少問題和缺陷。維護龐大的js建議使用精簡而不是混淆。

實際通過gzip壓縮以後,精簡和混淆差異很小。

精簡css

精簡css帶來的節省一般小於js,由於註釋和空白比較少。最大的潛在節省來自於優化css——合併相同的類,移除不使用的類等。css依賴順序的本質(成爲層疊樣式表的緣由)決定了這是一個複雜的問題。這個領域還須要進一步的研究和工具開發。

一般解決方案有使用顏色縮寫,用0代替0px。

規則11——避免重定向

重定向用於將用戶從一個URL從新路由到另外一個URL。重定向有不少種重。301和302是最經常使用的兩種。

重定向的類型和內容

一般針對HTML文檔進行重定向,但也可能用在請求頁面中的組件(圖片腳本)。

實現重定向有不少緣由:

  1. 網站從新設計
  2. 跟蹤流量
  3. 記錄廣告點擊
  4. 創建易於記憶的URL

301和302是使用的最多的。

<————
HTTP1.1 301 Moved  permanetely
Location: http://www.baidu.com
Content-type:text/html

瀏覽器會自動將用戶帶到Location字段給出的URL。重定向所必需的信息都出現了。301和302不會被緩存,除非有附加頭,如Expires和Cache-Control

將用戶重定向到其餘URL的方法

  • HTML文檔中的meta refresh 標籤能夠在其content屬性所指定的秒數以後重定向用戶
<meta http-equiv="refresh" content="0;  url=http://www.baidu.com" >
  • js也能夠執行重定向,documet.location設置爲指望的url

若是你必須重定向,最好的技術是使用標準的3XX HTPP狀態碼,主要是爲了確保後退按鈕能夠正常工做

HTML重定向小科普

頁面按期刷新,若是加url的,則會從新定向到指定的網頁,content後面跟的是時間(單位秒),把這句話加到指定網頁的<head></head>裏。通常也用在實時性很強的應用中,須要按期刷新的,如新聞頁面,論壇等,不過通常不會用這個,都用新的技術好比ajax等。

(題外話:因爲個人markdown編輯器是小書匠——web寫成的,下面代碼沒有引用的時候到帳右面預覽頁面一直閃爍。嚇了我一跳,這算bug麼~有一樣狀況的記得加引用符號)
<meta http-equiv="refresh" content="0; url=">'

通過一段時間轉到另外某個頁面,這裏0表示沒有延時,直接跳轉到後面的URL;把0改爲1,則延時1秒後跳轉。網頁自動計時跳轉。這個頁面跳轉的好處在於不須要JS調用,直接在html文件頭裏加入

<meta http-equiv="refresh[刷新-這裏指定動做]" content="5[這裏是時間];url=/article[這裏是跳轉的URL]">

重定向是如何損傷性能的

重定向時的第一個HTTP請求會阻塞後面html文檔的加載,四個重定向請求就會將用戶帶到指望HTML文檔的時間多花費一半。

重定向以外的其餘選擇

  1. 缺乏結尾的斜線/:這是最爲浪費和頻繁的,也是web開發人員沒注意的。沒有/時會致使301響應,這是不少web服務器的默認行爲,因此很簡單,url後面加一個/
  2. 鏈接網站:將舊網站鏈接到新網站只是重定向這種常見應用的一種表現形式。重定向下降了開發的複雜性,可是也損害了用戶體驗。
  3. 跟蹤內部流量:分析離開網頁首頁以後的流量去向。使用referer。難處在於只能分析內部,本身公司的,若是目標網站屬於其餘公司則不可能分析referer日誌了。
  4. 跟蹤出站流量:也不用重定向而是用信標(beacon)——一個hppt請求
  5. 美化URl: 使用重定向的另外一種動機是使URL美觀而且易於記憶。(這一節不太懂,有點亂,多)

規則12——刪除重複腳本

這一節有點扯和湊數。簡單網站手動查看排序依賴關係便可。如今大型網站須要使用grunt.webpack .seajs等前端自動化工具,處理依賴關係並進行打包,也就是模塊化等高級,方便的知識。

規則13——配置ETag

實體標籤(Entity Tag,ETag)是服務器和瀏覽器用於確認緩存組件有效性的一種機制。

服務器檢測緩存組件和原始服務器組件匹配的方式

若是緩存組件過時了或者用戶明確地從新加載了頁面,瀏覽器在重用以前必須首先檢查它是否有效。這稱做一個條件GET請求。雖然瀏覽器必須產生這個http請求,可是仍比簡單地下載全部已過時的組件效率高。若是瀏覽器組件是有效的(相互匹配)原始服務器則不會返回整個組件,而是返回304 not modifed狀態碼。

** 檢測匹配有兩種方式。

比較最新修改日期

  1. 第一次請求響應
————>
GET /i/xx.jpg HTTP 1.1
HOST www.xxx.com
<————
HTTP 1.1 20 OK
Last-Modified:true .12 dec 2015 03:03:09 GMT
Content-Length:1024
  1. 第二次請求響應
————>
GET /i/xx.jpg HTTP 1.1
HOST www.xxx.com
If-Modified-Since:True,12 dec 2015 03:03:09 GMT
<————
HTTP 1.1 304 not modifed

比較實體標籤

實體是咱們以前提到的組件的另外一種稱呼。ETag是惟一標識了一個組件的一個特定版本的字符串,必須帶上引號。這種爲驗證明體提供了更爲靈活的機制——能夠根據user-agent,accept-language頭而改變。

  1. 第一次請求響應
————>
GET /i/xx.jpg HTTP 1.1
HOST www.xxx.com
<————
HTTP 1.1 20 OK
Last-Modified:true .12 dec 2015 03:03:09 GMT
ETag:"10c34ba-8ba-abds3b3"
Content-Length:1024
  1. 第二次請求響應
————>
GET /i/xx.jpg HTTP 1.1
HOST www.xxx.com
If-Modified-Since:True,12 dec 2015 03:03:09 GMT
If-None-Match:"10c34ba-8ba-abds3b3"
<————
HTTP 1.1 304 not modifed

ETag帶來的問題

對於使用服務器集羣來處理請求的網站,匹配次數會大大下降。此時etag就下降了緩存效率,致使了沒必要要的請求、If-None-Match的優先級比If-Modified-Since的優先級更高,加重了問題嚴重性。

ETag用仍是不用

稍微麻煩一點,你要用php等腳本語言配置ETag頭。(若是你使用的是具備默認配置的Apache和iis)
你還能夠將ETag頭安全移除在apache配置文件中,減小它的壞處。
從ETag中移除ChangeNumber或者徹底移除ETag能夠避免當數據已經位於瀏覽器緩存中時進行沒必要要的和低效的下載。

谷歌,亞馬遜的組件中並無帶ETag,這一節有點雞肋感受。

規則14——使Ajax可緩存

終於到了web2.0的規則了

本書寫的時候google docs和mail剛出來,剛應用ajax,知識點不是不少。google的ajax請求中並不徹底是使用XMLHttpRequest,也有的使用了IFrame。

有的響應中由於數據隱私緣由而不能緩存,當數據被認爲是私有的時候,大多會在響應中使用

`Cache-Control:no-store`。

處理數據隱私的更好方法是使用安全通訊協議如安全套接字層(Secure Socket Layer,SSL)。SSL響應式能夠緩存的。好吧這又能夠講到https的知識了。不懂得能夠看下http相關知識。

在goole docs中緩存電子表格不像添加一個長久的expires頭那樣簡單,若是用戶修改了電子表格,咱們必須確保產生變化後不會再使用緩存的請求。

簡單的解決方案仍是使用查詢字符串。後端應該具備一個時間戳,來表示未次修改發生的時間,並將其嵌入到ajax請求的查詢字符串中。

/ar?id=[snip...]&srow=0&erow=100%t=15398503189

確保Ajax請求遵照性能指導,尤爲應具備長久的Expires頭。

15章——分析前10大網站,加本身總結經驗

  1. 使用yslow能夠清晰的看出14條軍規裏面A-F的等級速度。
  2. 頁面大小和響應時間成正比關係。比例係數0.94。
  3. 使用http1.1,默認開啓了持久化鏈接,效果好的多。
  4. 圖片轉換爲文字能夠減小請求數量。聯想到BootStrap中使用的icon字體圖標
  5. html中的img加上with,height,提早限制好,不用等到css再渲染肯定。
  6. 使用IFrame提供廣告的方式值得探討。IFrame實現了廣告與實際頁面的完全分離,使得二者的團隊和系統可以互不依賴。缺點是每一個IFrame都帶來一個額外http請求。使用IFrame又是合理的。由於廣告內容來自第三方一般包含本身的js代碼。將其放到iframe中也就將js放在了沙箱,能夠帶來極高安全性。(第三方代碼沒法訪問web頁面的命名空間) 將IFrame的src屬性設置爲about:blank 這不會生成任何HTTP流量。
  7. 預加載,能夠提早判斷用戶的訪問,後臺再下載所需組件。預加載是提升網站後續頁面加載速度的一種很好的方式。瀑布流中,圖片不到視窗中,不加載,延遲加載(這方面目前觀點不清)
  8. 使用png格式比gif格式圖片好。有png優化器,固然jpg格式也更好,適用場景不一樣。

基本完結了,之後有新的總結髮現,也會上傳更新分享

相關文章
相關標籤/搜索