文章首發: http://www.cnblogs.com/sprying/p/4251682.htmljavascript
本文先從網頁性能優化點提及,而後介紹怎麼實施性能優化,有哪些性能檢測工具。php
Yahoo!性能優化如今有35條,劃分紅了幾個類別,content、server、Cookie、CSS、JavaScript、Images、Mobile。css
合併Js、CSS文件,使用CSS sprites,使用Inline images(將base64的圖片數據放在頁面中會加大頁面大小,能夠放在可緩存的css中),使用iconfont。html
用戶80%~90%的時間是用來下載圖片、樣式、腳本、Flash等靜態資源,將靜態資源分發到離用戶最近的服務器上,可加快下載速度。前端
某站點設置靜態資源緩存後,瀏覽網頁時,一些公用的靜態資源已經在瀏覽其它頁面時下載緩存了,不用再發起請求。在緩存過時前,網頁內容也沒變更時,再次訪問網頁,全部靜態資源均可以從緩存讀取。java
合理配置緩存策略,在公用的靜態資源和請求數之間達到平衡,站點的不一樣頁面間能夠共用更多的公用的靜態資源。站點更新不只能即時反饋,並且作到網頁只需加載有變更的文件。node
http響應頭信息Expires、Cache-Control是緩存字段。這裏的緩存是指瀏覽器緩存,緩存過時前不用發起請求。jquery
瀏覽器中刷新頁面,會從新發起全部的請求;若是在地址欄按回車鍵,能夠看到設置緩存的靜態資源沒有再次發起請求。ios
服務端收到瀏覽器請求後,經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放在頁首沒意義。
background-color: expression( (new Date()).getHours()%2 ? "#B8D4FF" : "#F08A00" );
這種寫法只有IE支持,瀏覽器不只在渲染頁面或者改變頁面大小時觸發,甚至在滾動、移動鼠標時也觸發,統計發現操做了一次瀏覽器產生10000個evaluations。
實現結構、樣式、行爲分離,獨立成文件能夠利用瀏覽器緩存。
壓縮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運算
etag判斷一個靜態資源有沒有更新。請求一個靜態資源,返回的頭信息有etag字段,再次請求時,經過頭信息中If-None-Match字段將etag值帶過去,與服務端的文件etag值比對,若是一致就直接返回狀態碼 304,瀏覽器使用緩存中的靜態資源;不一致,服務器將最新文件傳輸過來。 etag值很重要,能反應出資源有無更新。通常的etag值inode-size-timestamp,雖然不一樣的服務器上inode值不同。 這樣若是靜態資源部署在多臺服務器上的,用etag就有問題。關閉etag,將判斷一個靜態資源有沒有更新就交給Last-Modified。
使用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延遲加載。
在頁面空閒時,預加載接下來操做可能須要的資源。有些網站改版時,第一次加載要加載許多新的靜態資源,致使用戶體驗不好,能夠在改版前預加載新的靜態資源。
不一樣瀏覽器對同一域名的併發數以下,將域名數控制在2-4個。
耗性能,即便是blank;阻塞父頁面的onload。
404請求會阻礙並行下載,而且瀏覽器可能去嘗試解析404返回內容發現有用的東西。
cookie在每次http請求會帶到服務端,cookie越大,傳輸的數據量越大。
若是站點域名是www.demo.com,靜態資源放在s.demo.com域名下,請求靜態資源時會將.demo.com下的cookie帶過去。 要作到free cookie,能夠申請個單獨的域名,好比domestic.com,拆分幾個二級域名,s0.demostatic.com,s1.demostatic.com。
Dom操做時,js要經過js-dom橋訪問dom,速度比js內部操做慢,因此要減小DOM操做。寫代碼時,
1)緩存指向dom的引用
2)離線操做節點,最後才更新到DOM中
3)避免Js操做一些屬性致使瀏覽器的頁面重繪
採用事件委託,避免重複綁定;若是操做DOM,事件回調綁定在DOMContentLoaded,避免使用onload。
沒法使用並行下載
IE下使用AlphaImageLoader filter來解決IE<7不支持透明,在下載圖像過程當中,使用這個屬性會阻塞瀏覽器,而且會加大內存消耗。避免使用而用png8代替,若是實在要使用AlphaImageLoader,用_filter。
優化圖像大小
不要在HTML中縮放圖像
iPhone手機最大能緩存25k,ios3有這個限制,可是有人在ios7上用css測試3Mb的文件,緩存了沒發起請求。
手機端請求是很昂貴的,打包成一個複合文本,減小請求數。但先要檢測終端是否支持。
兩種狀況下會發生
<img src=「」> var img = new Image(); img.src="";
瀏覽器可能發起請求當前頁面所在目錄,或者當前頁面,引發不必的麻煩,好比影響日誌統計,服務端從新生成頁面,瀏覽器從新接收引發的數據丟失。
諮詢了運維,目前萬網已經支持域名解析加速,能夠向com推送變動,1分鐘內生效,各省的域名解析服務器目前應該有雙向能力。
獲取靜態資源以前要創建通道,若是每次獲取靜態資源都要創建通道,會加大傳輸時間。
儘快渲染出,避免重排與重繪。
最大能夠將圖片減少到原圖片的1/3大小,是google制定了,其它瀏覽器廠商並不吃google的菜,只有chrome支持,直接在網頁保存webp格式的圖片,本地不能預覽,目前淘寶商品詳情頁採用這種格式圖片。
不要在外鏈中使用document.write加載資源
doc 返回編碼charset=uft-8,加快解析;不要在html中設置,貌似ie8下有bug。
將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
用jquery選擇器選中的元素,若是還需第二次使用,建議緩存到變量中,避免重複的建立jQuery對象。
在查找元素時,使用對象比使用數組更有效,使用數組還須要遍歷,但對象不會保持默認的排序。
dom操做是有代價的,訪問它
有些性能優化點,須要前端工程師在編碼過程當中遵照;有些須要配置服務器,設置緩存、etag、gzip;ajax緩存須要後臺提供接口時設置;一些關鍵的優化點,須要前端工程支持。
在模塊化開發時,細分了許多小文件,如何合併壓縮腳本、樣式,並在多頁面中利用好緩存,如何使css spirites、inline images用起來很easy。如何保證將樣式表放在頁面上方、將腳本放在底部、剔除重複的腳本。
expires 瀏覽器本地緩存設置
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的執行效率,還有監控網頁的加載速度,如首屏加載時間。
可爲項目後續優化提供參考。分數低,不必定網頁首屏加載慢。
按照yahoo!的網頁性能優化標準來評分。
我在用yslow過程當中,發現惋惜的是,動態腳本注入的,沒有統計到。
參照google網頁性能優化標準來評測,下面是一個網站的評測
如避免重定向、壓縮圖片、指定緩存驗證工具、啓用 Keep-Alive等這些建議在yslow中沒有的,因此跑完yslow,能夠再跑下pagespeed。
須要本地安裝,目前只支持IE,firefox。工具除了提供常規的性能優化建議外,還統計了Js方法的執行時間。
上面的數據,是使用seajs.use後,下載完依賴模塊文件,js執行耗時相關信息,能夠一層層定位,最後定位到是哪一個函數執行比較耗時,好比過多使用append。
google的另一套工具,speed tracer,追蹤加載過程,以圖形化方式展現,有執行時間,能夠定位到Js代碼,但通常都定位到封裝庫的源碼中。
從分佈在各省市、運營商的節點,測試出不一樣的系統、瀏覽器對同一網頁的加載性能、首屏時間、腳本報錯統計;更加接近用戶角度。須要購買服務。
下面是某站點一週的首屏加載時間統計
下面是即時監測某網頁的一些數據
https://developer.yahoo.com/performance/rules.html
16毫秒的優化——Web前端性能優化的微觀分析-->從js角度來分析