題記:無心間在公司圖書館看到這本書,感受內容寫得很不錯,很細頗有條理。雖然本身並不是前端工程師,然而也須要對此有所瞭解,供之後在架構設計、系統優化時考慮這些因素,特在此將對該書進行摘錄,供不時之需。也但願有更多的同行可以瞭解到這本書,進而提高本身所負責網站的展示速度,給與用戶更好地訪問體驗。css
只有10-20%的最終用戶響應時間花在了下載HTML文檔上。其他的80-90%時間花在了下載頁面中的全部組件上。
HTTP概述
- 壓縮
- 條件GET請求
- Expire
- Keep-Alive
規則一、減小HTTP請求
- 圖片地圖:將多個圖片合併成一個,然後經過css定位顯示不一樣的位置
- CSS Sprites:同上
- 內聯圖片
- 合併腳本和樣式表
規則二、使用內容發佈網絡(CDN,Content Delivery Network)
規則三、添加Expires頭
- Expires頭:在這一日期/時間以後,響應將被認爲是無效的
- Max-Age: 設置相對有效時間Cache-Control:max-age=100
- 空緩存VS完整緩存:儘量將頁面內容放入大緩存中
- 不只僅是圖片:圖片應該使用緩存,但這一最佳實踐不該該僅限於圖片
- 修訂文件名:爲可以獲取最新的文件,最有效的解決方案是修改其全部連接,這樣,全新的請求將從原始服務器下載最新的內容。
規則四、壓縮組件
- gzip:Accept-Encoding:gzip,deflate。gzip是目前最流行和最有效的壓縮方法,是最理想的壓縮方法
- 壓縮內容:壓縮腳本和樣式表是很是值得的,同時還有XML和JSON在內的文本。圖片和PDF不該該壓縮,由於它們原本就已經被壓縮了。
- 節省率:壓縮一般能將響應的數據量減小將近70%
- gzip配置:不一樣的web服務器有不一樣的gzip配置方式,但大多支持gzip
- 代理緩存:Web服務器基於Accept-Encoding來檢測是否對響應進行壓縮。無論是否壓縮過,瀏覽器都會基於響應中的其餘HTTP頭如Expires和Cache-Control來緩存響應。因爲壓縮的決定是基於Accept-Encoding請求頭的,所以須要在服務器的Vary響應頭中包含Accept-Encoding。
- 邊緣情形:服務器和客戶端的壓縮對等性看似簡單,但必須正確才行。不管是客戶端仍是服務器發生錯誤(發送壓縮內容到不支持它的客戶端、忘記將壓縮內容聲明爲已經進行了gzip編碼等),頁面都會被破壞。錯誤並不會常常發生,但它們是必須考慮的邊緣情形(Edge Case)。這種狀況雖然能夠經過瀏覽器白名單方式解決,但設置瀏覽器白名單的指令過於複雜,沒法使用HTTP頭進行編碼。最佳作法是將User-Agent做爲代理的另一種判斷標準添加到Vary頭中Vary:Accept-Encoding,User-Agent
規則五、將樣式表放在頂部
規則5對於加載頁面所需的實際時間沒有太多影響,它影響更多的是瀏覽器對這些組件順序的反應。爲避免當樣式變化時重繪頁面中的元素,瀏覽器會等待位於底部的樣式表加載完成後纔會呈現,這時瀏覽器會延遲任何可視化組件。實際上,用戶感受緩慢的頁面反而是可視化組建加載得更快的頁面。使用LINK標籤將樣式表放在文檔的HEAD中能夠解決該問題。前端
在使用樣式表時,頁面逐步呈現會被阻止,直到全部的樣式表下載完成。將樣式表移到文檔head中,這樣就能首先下載它們而不會阻止頁面呈現。web
規則六、將腳本放在底部
- 並行下載 對響應時間影響最大的是頁面中組件的數量,若是一個Web頁面平均地將其組件分別放在兩個主機名下,總體響應時間將能夠減小大約一半。但並行下載數量並非越多越快,由於增長並行下載數量是有開銷的,其優劣取決於帶寬和cpu速度。
- 腳本阻塞下載 並行下載組件的優勢是很明顯的,然而,在下載腳本時並行下載實際上被禁用的。即便使用了不一樣的主機名,瀏覽器也不會啓動其餘的下載。其中一個緣由是,腳本可能使用document.write來修改頁面內容,所以瀏覽器會等待,已確保頁面可以恰當地佈局。另外一個緣由是爲了保證腳本可以按照正確的順序執行。
在使用腳本時,對於全部位於腳本如下的內容,逐步呈現都被阻塞了。將腳本放在頁面越靠下的地方,意味着越多的內容能逐步地呈現。後端
規則七、避免css表達式
規則八、使用外部JavaScript和Css
- 純碎而言,內聯快一些
- 頁面查看 每一個用戶產生的頁面查看越少,內聯JavaScript和Css的論據越強勢。另外一方面,若是普通用戶可以產生不少的頁面查看,瀏覽器極可能將(具備長久的Expires頭的)外部文件放在其緩存中。
- 組件重用 若是你的網站中的每個頁面都使用了相同的JavaScript和Css,使用外部文件能夠提升這些組件的重用率。在這種狀況下使用外部文件更加具備優點,由於當用戶在頁面間瀏覽時,JavaScript和Css組件已經位於瀏覽器的緩存中了。
- 動態內聯 若是主頁服務器知道一個組件是否在瀏覽器的緩存中,它能夠在內聯和使用外部文件之間作出最佳選擇。儘管服務器不能查看瀏覽器緩存中有些什麼,但能夠用cookies作指示器。若是cookie不存在,就內聯了JavaScript和Css。若是cookie出現了,則有可能外部組件位於瀏覽器的緩存中,並使用了外部文件。
規則九、減小DNS查找
Internet是經過IP地址來查找服務器的。因爲IP地址很難記憶,一般使用包含主機名的URL來取代它,但當瀏覽器發送其請求時,IP地址仍然是必需的。這就是Domain Name System(DNS) 所處的角色。DNS也有開銷,一般瀏覽器查找一個給定的主機名的IP地址要花費20-120毫秒。響應時間依賴於DNS解析器(一般由你的ISP提供)、它所承擔的請求壓力、你與它之間的距離和你的帶寬速度。瀏覽器
- DNS緩存 DNS查找能夠被緩存起來提升性能。這種緩存能夠發生在由你的ISP或局域網中的一臺特殊的緩存服務器上,但這裏探討的是發生在獨立用戶的計算機上的DNS緩存。在用戶請求了一個主機名以後,DNS信息會留在操做系統的DNS緩存中,以後對於該主機名的請求將無需進行過多的DNS查找,至少短期內不須要。·
- 影響DNS緩存的因素 首先,服務器能夠代表記錄能夠被緩存多久。查找返回的DNS記錄包含了一個存活時間(Time-to-live,TTL)值。該值告訴客戶端能夠對該記錄緩存多久,儘管操做系統緩存會考慮TTL值,但瀏覽器一般忽略該值,並設置它本身的時間限制。另外瀏覽器對緩存的DNS記錄的數量也有限制,TTL設置值一般是1天。
- 減小DNS查找 當客戶端的DNS緩存爲空(瀏覽器和操做系統都是)時,DNS查找的數量與Web頁面中惟一主機名的數量相等。這包括頁面URL、圖片、腳本文件、樣式表、Flash對象等的主機名。減小惟一主機名的數量就能夠就能夠減小DNS查找的數量。
- 經過使用Keep-Alive和較少的域名來減小DNS查找
規則十、精簡JavaScript
JavaScript做爲一門解釋型語言,是構建Web頁面的首選。當以快速原型爲基準開發用戶界面時,解釋語言要優於其餘語言。緩存
- 精簡 是從代碼中移除沒必要要的字符以減小其大小,進而改善加載時間的實踐。在代碼被精簡後,全部的註釋以及沒必要要的空白字符(空格、換行和製表符)都將被移除。對於JavaScript而言,這能夠改善響應時間效率,由於須要下載的文件大小減小了。精簡JavaScript最流行的工具是JSMin。
- 混淆 是能夠應用在源代碼上的另一種優化方式。和精簡同樣,它也會移除註釋和空白,同時它還會改寫代碼。做爲改寫的一部分,函數和變量的名字將被轉換爲更短的字符串,這時的代碼更加精煉。可是會帶來三個弊端:可能引入錯誤、增長調試難度、須要對JavaScript關鍵字標記
- 內聯腳本 內聯的JavaScript塊也應該精簡
規則十一、避免重定向
重定向用於將用戶從一個URL從新路由到另外一個URL,種類有不少,經常使用的是301和302。它是損傷性能的,能夠採用Alias、mod_rewirte、DirectorySlash和直接鏈接代碼來避免重定向。服務器
規則十二、移除重複腳本
- 重複腳本--確有其事 開發一個網站須要極大數量的資源,除了核心團隊要構建網站外,其餘團隊也會向頁面貢獻HTML代碼。因爲來自不一樣團隊的不少人都要向頁面中添加HTML,很容易想到相同的腳本可能會被添加屢次
- 重複腳本傷害性能 引發沒必要要的HTTP請求和執行JavaScript所消耗的時間
規則1三、配置ETag
實體標籤(Entity Tag,ETag)是Web服務器和瀏覽器用於確認緩存組件的有效性的一種機制。減小呈現頁面時所必需的HTTP請求的數量是加速用戶體驗的最佳方式。能夠經過最大化瀏覽器緩存組件的能力來實現這一目標,但當網站被宿主在多於一臺服務器上時,ETag頭可能會阻礙緩存。cookie
ETag帶來的問題 ETag的問題在於,一般使用組件的某些屬性來構造它,這些屬性對於特定的、寄宿了網站的服務器來講是惟一的。當瀏覽器從一臺服務器上獲取了原始組件,以後又向另一臺不一樣的服務器發起條件GET請求時,ETag是不會匹配的----而對於使用服務器集羣來處理請求的網站來講,這是很常見的一種狀況。默認狀況下,對於擁有多臺服務器的網站,Apache和IIS向ETag中嵌入的數據都會大大地下降有效性驗證的成功率。網絡
解決該問題的兩種方式:選擇ETag的配置方式或者直接移除ETag前端工程師
規則1四、使Ajax可緩存
Ajax表示異步JavaScript和XML(Asynchronous JavaScript and XML),儘管今天除了XML有不少其餘選擇,最著名的是JSON。Ajax的目的是爲了突破Web本質的開始--中止交互方式。向用戶顯示一個白屏而後重繪整個頁面不是一種後的用戶體驗。而Ajax在UI和Web服務器之間插入了一層。這個Ajax層位於客戶端,與Web服務器進行交互以獲取請求的信息,並與表現層交互,僅更新哪些必要的組件。它將Web體驗從「瀏覽頁面」轉變爲「與應用程序進行交互」。
Ajax的一個明顯優勢是向用戶提供了及時反饋,由於它異步地從後端Web服務器請求信息。但Ajax並不保證用戶就不會一邊玩弄本身的手指一邊等着「異步JavaScript和XML」返回響應,記住「異步」並無暗示「即時」,這一點很重要。用戶是否須要等待的關鍵因素在於Ajax請求是被動的仍是主動的。被動請求是爲了未來使用而預先發起的。主動請求是基於用戶當前的操做而發起的。
改善Ajax請求的最重要的方式就是使響應可緩存,前面第四、九、十、十一、13原則也適用於此。
確保Ajax請求遵照性能指導,尤爲應具備長久的Expires頭。