網頁性能優化

文章首發: http://www.cnblogs.com/sprying/p/4251682.htmljavascript

本文先從網頁性能優化點提及,而後介紹怎麼實施性能優化,有哪些性能檢測工具。php

Yahoo!性能優化35條

Yahoo!性能優化如今有35條,劃分紅了幾個類別,content、server、Cookie、CSS、JavaScript、Images、Mobile。css

減小HTTP的請求數

合併Js、CSS文件,使用CSS sprites,使用Inline images(將base64的圖片數據放在頁面中會加大頁面大小,能夠放在可緩存的css中),使用iconfont。html

CDN

用戶80%~90%的時間是用來下載圖片、樣式、腳本、Flash等靜態資源,將靜態資源分發到離用戶最近的服務器上,可加快下載速度。前端

使用緩存

某站點設置靜態資源緩存後,瀏覽網頁時,一些公用的靜態資源已經在瀏覽其它頁面時下載緩存了,不用再發起請求。在緩存過時前,網頁內容也沒變更時,再次訪問網頁,全部靜態資源均可以從緩存讀取。java

合理配置緩存策略,在公用的靜態資源和請求數之間達到平衡,站點的不一樣頁面間能夠共用更多的公用的靜態資源。站點更新不只能即時反饋,並且作到網頁只需加載有變更的文件。node

http響應頭信息Expires、Cache-Control是緩存字段。這裏的緩存是指瀏覽器緩存,緩存過時前不用發起請求。jquery

瀏覽器中刷新頁面,會從新發起全部的請求;若是在地址欄按回車鍵,能夠看到設置緩存的靜態資源沒有再次發起請求。ios

Gzip壓縮

服務端收到瀏覽器請求後,經gzip壓縮後傳輸的大小可減少70%,瀏覽器接收後解壓。pdf、圖片自己已經壓縮了再也不須要gzip。通常文檔類型默認啓用了gzip,其它靜態資源,好比樣式、腳本要單獨配置啓用gzip。nginx

將樣式表放在頁面上方

網頁渲染是從上往下執行,邊下載邊解析頁面元素,將樣式放在頁尾,下載完樣式後執行會使頁面樣式閃爍。

貌似有些瀏覽器只有等css下載好了以後,才展現出頁面。chrome訪問過國外網站,出現過css沒下載好,整個頁面都是空白。

將腳本放在底部

瀏覽器中JavaScript與UI共用一個線程,如今的瀏覽器Js下載是並行的(IE八、Firefox三、Chrome2是串行),下載時會阻止頁面一些資源加載(google說下載、解釋、執行都會阻止),如圖片;執行是阻塞瀏覽器的頁面的下載和渲染,因此引入的Js要放在頁末。

Ps:

css文件下載是並行的,不阻礙其它文件下載。而Js基本都用來操做Dom的,代碼的執行要等Dom渲染完成,因此通常Js代碼能夠直接放在頁尾,若是放在頁首,處理Dom元素的Js代碼要放在Dom下載完成的事件回調內。

除非你在DOM標籤內部指定事件類型和回調函數名(不推薦),否則把Js放在頁首沒意義。

避免使用CSS中的Expressions

background-color: expression( (new Date()).getHours()%2 ? "#B8D4FF" : "#F08A00" );

 這種寫法只有IE支持,瀏覽器不只在渲染頁面或者改變頁面大小時觸發,甚至在滾動、移動鼠標時也觸發,統計發現操做了一次瀏覽器產生10000個evaluations。

將JavaScript和CSS獨立成外部文件

實現結構、樣式、行爲分離,獨立成文件能夠利用瀏覽器緩存。

壓縮 JavaScript 和CSS

壓縮JavaScript時,若是使用模塊化開發時,好比seajs不能直接壓縮,要先transport下,具體可參考spm的grunt-cmd-transport插件

避免重定向

Request URL:http://yun.ys7.com/gc.html
Request Method:GET
Status Code:301 Moved Permanently (from cache)

Response Headers
Content-Length:178
Content-Type:text/html
Date:Tue, 03 Feb 2015 15:34:42 GMT
Location:http://i.ys7.com/square/index.jsp
Server:nginx 

重定向的http請求返回301或者302,返回的報文的body部分是空的。

上面是訪問http://yun.ys7.com/gc.html,服務器告訴瀏覽器重定向到//i.ys7.com/square/index.jsp,瀏覽器從新發起//i.ys7.com/square/index.jsp請求。

瀏覽器訪問網頁,經過重定向而發起兩次請求,影響性能。

剔除重複的腳本

團隊規模越大、代碼越多,越有可能出現;若是出現,會致使不必的請求和Js運算

配置ETags

etag判斷一個靜態資源有沒有更新。請求一個靜態資源,返回的頭信息有etag字段,再次請求時,經過頭信息中If-None-Match字段將etag值帶過去,與服務端的文件etag值比對,若是一致就直接返回狀態碼 304,瀏覽器使用緩存中的靜態資源;不一致,服務器將最新文件傳輸過來。 etag值很重要,能反應出資源有無更新。通常的etag值inode-size-timestamp,雖然不一樣的服務器上inode值不同。 這樣若是靜態資源部署在多臺服務器上的,用etag就有問題。關閉etag,將判斷一個靜態資源有沒有更新就交給Last-Modified。

使用AJAX緩存

使用get類型的ajax請求,後臺處理接口時,加上http頭信息Expires,之後瀏覽器再次發起請求時,在緩存的時間內,直接從瀏覽器緩存中讀取。

好比有個網頁聯繫人列表不常常變更,ajax請求聯繫人列表接口的url帶上資源標誌id(id是頁面初始化時由後臺帶回來,後臺根據聯繫列表生成,若是列表變化了,id也變化),第一次訪問時,ajax調用接口緩存了;第二次調用時,若是聯繫人列表沒有變更過,id仍是不變,url也不會變,直接從緩存讀取。

儘早刷新輸出緩衝

後臺生成一個完整的頁面,要經歷數據庫查詢,一系列業務流程,假設耗時爲A,再由服務器容器轉化成html頁面返回給瀏覽器。瀏覽器邊下載邊解析DOM,下載頁面相關的靜態資源,假設耗時爲B,整個耗時就是(A+B)。 若是A和B並行呢? 服務器容器先將靜態資源的相關內容返回給瀏覽器,服務器一邊進行查詢等耗時操做(A),瀏覽器同時一邊解析DOM中到引用靜態資源,就開始下載(B)。 目前php支持。

Example:

... <!-- css, js -->
</head>
<?php flush(); ?>
<body>
... <!-- content -->

使用GET來完成AJAX請求

使用post請求,瀏覽器要進行兩個過程,先發頭信息,再發送數據。而使用get,請求數據都在url上,只需發一次,IE下最大長度爲2k,從語義化角度,來講,get是獲取數據的意思。get請求會被緩存,post不會,post傳輸比較安全。

推遲加載內容

將全部靜態資源都下載好了以後,再執行Js渲染等操做,會影響首屏內容最快顯示。在模塊化開發時,當用到插件效果時去下載,或者等瀏覽器加載的標籤轉圈圈好了以後,觸發load以後再執行其它下載,使用require.async延遲加載。

預加載

在頁面空閒時,預加載接下來操做可能須要的資源。有些網站改版時,第一次加載要加載許多新的靜態資源,致使用戶體驗不好,能夠在改版前預加載新的靜態資源。

減小DOM元素數量

將靜態資源劃分到不一樣的靜態服務上

不一樣瀏覽器對同一域名的併發數以下,將域名數控制在2-4個。

使iframe的數量最小

耗性能,即便是blank;阻塞父頁面的onload。

不要出現404錯誤

404請求會阻礙並行下載,而且瀏覽器可能去嘗試解析404返回內容發現有用的東西。

減少Cookie大小

cookie在每次http請求會帶到服務端,cookie越大,傳輸的數據量越大。

若是站點域名是www.demo.com,靜態資源放在s.demo.com域名下,請求靜態資源時會將.demo.com下的cookie帶過去。 要作到free cookie,能夠申請個單獨的域名,好比domestic.com,拆分幾個二級域名,s0.demostatic.com,s1.demostatic.com。

減小DOM訪問

Dom操做時,js要經過js-dom橋訪問dom,速度比js內部操做慢,因此要減小DOM操做。寫代碼時,

1)緩存指向dom的引用

2)離線操做節點,最後才更新到DOM中

3)避免Js操做一些屬性致使瀏覽器的頁面重繪

優化事件綁定

採用事件委託,避免重複綁定;若是操做DOM,事件回調綁定在DOMContentLoaded,避免使用onload。

沒法使用並行下載

避免使用濾鏡

IE下使用AlphaImageLoader filter來解決IE<7不支持透明,在下載圖像過程當中,使用這個屬性會阻塞瀏覽器,而且會加大內存消耗。避免使用而用png8代替,若是實在要使用AlphaImageLoader,用_filter。

優化圖像

優化圖像大小

優化CSS Spirite

不要在HTML中縮放圖像

favicon.ico要小並且可緩存

保持單個內容小於25K(針對手機)

iPhone手機最大能緩存25k,ios3有這個限制,可是有人在ios7上用css測試3Mb的文件,緩存了沒發起請求。

打包組件成複合文本(針對手機)

手機端請求是很昂貴的,打包成一個複合文本,減小請求數。但先要檢測終端是否支持。

避免img標籤的src爲空

兩種狀況下會發生

<img src=「」>

var img = new Image();
img.src=""; 

瀏覽器可能發起請求當前頁面所在目錄,或者當前頁面,引發不必的麻煩,好比影響日誌統計,服務端從新生成頁面,瀏覽器從新接收引發的數據丟失。

其它優化點

DNS域名解析加速

諮詢了運維,目前萬網已經支持域名解析加速,能夠向com推送變動,1分鐘內生效,各省的域名解析服務器目前應該有雙向能力。

Http請求要保持Keep-Alive

獲取靜態資源以前要創建通道,若是每次獲取靜態資源都要創建通道,會加大傳輸時間。

圖片要聲明width和height

儘快渲染出,避免重排與重繪。

使用webp格式圖片

最大能夠將圖片減少到原圖片的1/3大小,是google制定了,其它瀏覽器廠商並不吃google的菜,只有chrome支持,直接在網頁保存webp格式的圖片,本地不能預覽,目前淘寶商品詳情頁採用這種格式圖片。

document.write

不要在外鏈中使用document.write加載資源

文檔編碼類型

doc 返回編碼charset=uft-8,加快解析;不要在html中設置,貌似ie8下有bug。

使用MXHR

將css、圖片、js資源整合成一個文件請求,程序後臺使用分隔符將這些數據分隔開來,而後在前臺拆分;還能夠readystatus=3邊傳輸邊解析。缺點是,不能緩存;老版本的IE不支持readystatus =3和data:url,在Ie8中就能夠了,必須在Ie六、7下設法變通。以爲在淘寶,瀏覽商品許多圖片時,用這個不錯,不過淘寶商品的圖片,不在當前發起請求文檔的同個域名下,有跨域問題吧

無阻塞的腳本

將腳本放在頁面底部是Yahoo!性能優化的優化點,其實,是解決腳本下載與執行是阻塞問題。若是使用無阻塞的腳本呢? Js引擎和UI線程公用一個線程,無阻塞引入腳本,可解決在引入js時,阻塞UI渲染。

1) 在script標籤加入defer屬性

當頁面解析到script標籤時,開始下載Js文件,頁面並不等待繼續解析,不會阻礙其它頁面資源的下載,因爲只有 Explorer 4+ 和 Firefox 3.5+支持,這裏就不詳細討論。

2) 動態腳本注入(dynamic script tag insert)

在body結束標籤處,經過Js的Dom操做,新建script元素,設置好src以後,添加到head中(最好是head,body中可能),就開始下載,不會影響瀏覽器UI線程,下載完觸發script標籤的onload事件(不一樣瀏覽器有差別),若是建立多個script後並行下載,有可能後增的Js先下載完成,有的瀏覽器會等待,好比FireFox、Opera,有的先下載完先執行。對於有依賴關係的Js文件,能夠在前一個Js下載完成後,再加載新的Js。目前豆瓣的do.js、in.js都根據這個原理實現的封裝。

3) XMLHttpRequest注入

在項目裏,咱們俗稱ajax,請求的路徑改成一個js的url,在返回成功的回調裏面,進行Dom操做,建立一個script,將請求獲得的響應報文,設置爲scritpt的dom對象的text屬性。 評析:不能請求跨域的js,設置text屬性後,立馬就執行Js,因此經過控制設置text屬性的時機,來控制Js的執行。不過這種方法仍是被不多用,多是將js內容直接填充到html頁面的script元素中,總人本能以爲不整潔吧。

優化數據傳輸

傳輸數據的幾種方式

xhr jsonp 獲取信息,json-padding,基於動態腳本注入,支持跨域 Beacons 圖片信標,簡單效率高,通常用來發送頁面統計信息

數據的傳輸格式

xml、Json、拼接的字符串、json-p

數據的本地存儲

使用ajax緩存、localstorage

提高Js代碼的執行效率

緩存DOM節點查找的結果

用jquery選擇器選中的元素,若是還需第二次使用,建議緩存到變量中,避免重複的建立jQuery對象。

用hash-table來優化查找

在查找元素時,使用對象比使用數組更有效,使用數組還須要遍歷,但對象不會保持默認的排序。

用innerHTML代替DOM操做,減小DOM操做次數

dom操做是有代價的,訪問它

實踐性能優化

有些性能優化點,須要前端工程師在編碼過程當中遵照;有些須要配置服務器,設置緩存、etag、gzip;ajax緩存須要後臺提供接口時設置;一些關鍵的優化點,須要前端工程支持。

前端工程化支持

在模塊化開發時,細分了許多小文件,如何合併壓縮腳本、樣式,並在多頁面中利用好緩存,如何使css spirites、inline images用起來很easy。如何保證將樣式表放在頁面上方、將腳本放在底部、剔除重複的腳本。

nginx緩存設置

expires 瀏覽器本地緩存設置

語法:expires [time|epoch|max|off]
默認值:expires off
使用字段:http, server, location

off 將禁止修改頭部中的 Expires和Cache-Control字段。
Time控制「Cache-Control」的值,負數表示no-cache
epoch 將Expires頭設置爲1 January, 1970 00:00:01 GMT。
max 將Expires頭設置爲31 December 2037 23:59:59 GMT,將Cache-Control最大化到10 年。
expires 30d;
expires 1h;
 

nginx的gzip設置

nginx 在http{….}兩個大括號之間,配置gzip段以下:

gzip on;
gzip_min_length 1k;
gzip_buffers 16 64k;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_types text/plain application/x-javascript text/css application/xml;
gzip_vary on;

 

性能檢測工具

性能監測工具我劃分爲3類,一類檢測規範的遵循狀況,一類檢測Js的執行效率,還有監控網頁的加載速度,如首屏加載時間。

類型一

可爲項目後續優化提供參考。分數低,不必定網頁首屏加載慢。

  • yslow(Firfox、chrome的插件)

  按照yahoo!的網頁性能優化標準來評分。

    

  我在用yslow過程當中,發現惋惜的是,動態腳本注入的,沒有統計到。

 

  • pagespeed

  參照google網頁性能優化標準來評測,下面是一個網站的評測

  

 

  如避免重定向、壓縮圖片、指定緩存驗證工具、啓用 Keep-Alive等這些建議在yslow中沒有的,因此跑完yslow,能夠再跑下pagespeed。

類型二

  • DynaTrace Ajax Edition

  須要本地安裝,目前只支持IE,firefox。工具除了提供常規的性能優化建議外,還統計了Js方法的執行時間。

    

  上面的數據,是使用seajs.use後,下載完依賴模塊文件,js執行耗時相關信息,能夠一層層定位,最後定位到是哪一個函數執行比較耗時,好比過多使用append。

  • speed tracer

  google的另一套工具,speed tracer,追蹤加載過程,以圖形化方式展現,有執行時間,能夠定位到Js代碼,但通常都定位到封裝庫的源碼中。

    

類型三

  • 基調

  從分佈在各省市、運營商的節點,測試出不一樣的系統、瀏覽器對同一網頁的加載性能、首屏時間、腳本報錯統計;更加接近用戶角度。須要購買服務。

  下面是某站點一週的首屏加載時間統計

  

  

  下面是即時監測某網頁的一些數據

  

 

參考文章

https://developer.yahoo.com/performance/rules.html

其它文章

16毫秒的優化——Web前端性能優化的微觀分析-->從js角度來分析

相關文章
相關標籤/搜索