1.域名是從右至左解析的,也就是說用戶輸入www.baidu.com這個域名是從com開始解析;在從頂級域名中查找baidu這個域名,找到了就返回www.baidu.com的內容,假如沒有就查找二級域名(相似xxx.baidu.com);php
2.前端有2棵樹,一個是DOM樹,一個是render樹(也叫呈現樹);DOM樹和樣式結構體組合後構建render樹;區別:render樹能識別樣式,render樹中每一個DOM節點都有本身的style,並且 render樹不包含隱藏的節點 (好比display:none的節點,還有head節點),由於這些節點不會用於呈現,並且不會影響呈現的,因此就不會包含到 render樹中。注意 visibility:hidden隱藏的元素仍是會包含到 render樹中的,由於visibility:hidden 會影響佈局(layout),會佔有空間。根據CSS2的標準,render樹中的每一個節點都稱爲Box (Box dimensions),理解頁面元素爲一個具備填充、邊距、邊框和位置的盒子。css
3.當render樹中的一些元素須要更新屬性,而這些屬性只是影響元素的外觀,風格,而不會影響佈局的,好比background-color。則就叫稱爲重繪。html
4.當render樹中的一部分(或所有)由於元素的規模尺寸,佈局,隱藏等改變而須要從新構建。這就稱爲迴流。(與盒子模型有關的:邊框,內外邊距,位置,字體大小等等)前端
注意:迴流必將引發重繪,而重繪不必定會引發迴流。web
5.前端渲染流程分爲:http頁面請求和瀏覽器js引擎;有哪些內容,請看下圖:數據庫
說了這麼多,那如何作前端性能優化勒?express
首先要明白:每一個產品的優化方案都不同;好比視頻和新聞類的網站就不同,視頻優化的是加載速度,播放器這些東西;新聞主要是優化圖片等資源;但萬變不離其宗,有些通用的方法能幫你解決大部分問題;咱們先看看從技術的出發點看如何解決性能優化:api
看完上圖相信你也大概清楚要作些什麼了,下面我來解釋通用的優化性能方案——雅虎的35條軍規(雖然已通過時了,但好東西是不會過期的):跨域
80%的終端用戶響應時間都花在了前端上,其中大部分時間都在下載頁面上的各類組件:圖片,樣式表,腳本,Flash等等。減小組件數必然可以減小頁面提交的HTTP請求數。這是讓頁面更快的關鍵。瀏覽器
合併文件是經過把全部腳本放在一個文件中的方式來減小請求數的,固然,也能夠合併全部的CSS。若是各個頁面的腳本和樣式不同的話,合併文件就是一項比較麻煩的工做了,但把這個做爲站點發布過程的一部分確實能夠提升響應時間。
CSS Sprites是減小圖片請求數量的首選方式。把背景圖片都整合到一張圖片中,而後用CSS的background-image
和background-position
屬性來定位要顯示的部分。
圖像映射能夠把多張圖片合併成單張圖片,總大小是同樣的,但減小了請求數並加速了頁面加載。圖片映射只有在圖像在頁面中連續的時候纔有用,好比導航條。給image map設置座標的過程既無聊又容易出錯,用image map來作導航也不容易,因此不推薦用這種方式。
Base64編碼。這樣會增長HTML文件的大小,把行內圖片放在(緩存的)樣式表中是個好辦法,並且成功避免了頁面變「重」。但目前主流瀏覽器並不能很好地支持行內圖片。
減小頁面的HTTP請求數是個起點,這是提高站點首次訪問速度的重要指導原則。
減小不一樣主機名的數量同時也減小了頁面可以並行下載的組件數量,避免DNS查找削減了響應時間,而減小並行下載數量卻增長了響應時間。個人原則是把組件分散在2到4個主機名下,這是同時減小DNS查找和容許高併發下載的折中方案。
重定向用301和302狀態碼,下面是一個有301狀態碼的HTTP頭:
有一種常見的極其浪費資源的重定向,並且web開發人員通常都意識不到這一點,就是URL尾部缺乏一個斜線的時候。例如,跳轉到http://astrology.yahoo.com/astrology會返回一個重定向到http://astrology.yahoo.com/astrology/的301響應(注意添在尾部的斜線)。在Apache中能夠用Alias
,mod_rewrite
或者DirectorySlash
指令來取消沒必要要的重定向。
咱們一塊兒看看例子,一個Web 2.0的電子郵件客戶端用了Ajax來下載用戶的通信錄,以便實現自動完成功能。若是用戶從上一次使用以後再沒有修改過她的通信錄,並且Ajax響應是可緩存的,有還沒有過時的Expires或者Cache-Control HTTP頭,那麼以前的通信錄就能夠從緩存中讀出。必須通知瀏覽器,應該繼續使用以前緩存的通信錄響應,仍是去請求一個新的。能夠經過給通信錄的Ajax URL裏添加一個代表用戶通信錄最後修改時間的時間戳來實現,例如&t=1190241612
。若是通信錄從上一次下載以後再沒有被修改過,時間戳不變,通信錄就將從瀏覽器緩存中直接讀出,從而避免一次額外的HTTP往返消耗。若是用戶已經修改了通信錄,時間戳也能夠確保新的URL不會匹配緩存的響應,瀏覽器將請求新的通信錄條目。
JavaScript是分隔onload事件以前和以後的一個理想選擇。例如,若是有JavaScript代碼和支持拖放以及動畫的庫,這些均可以先等會兒,由於拖放元素是在頁面最初渲染以後的。其它能夠延遲加載的部分包括隱藏內容(在某個交互動做以後纔出現的內容)和摺疊的圖片。
工具可幫你減輕工做量:YUI Image Loader能夠延遲加載摺疊的圖片,還有YUI Get utility是一種引入JS和CSS的簡單方法。Yahoo!主頁就是一個例子,能夠打開Firebug的網絡面板仔細看看。
預加載可能看起來和延遲加載是相反的,但它其實有不一樣的目標。經過預加載組件能夠充分利用瀏覽器空閒的時間來請求未來會用到的組件(圖片,樣式和腳本)。用戶訪問下一頁的時候,大部分組件都已經在緩存裏了,因此在用戶看來頁面會加載得更快。
實際應用中有如下幾種預加載的類型:
大量的DOM元素是一種徵兆——頁面上有些內容無關的標記須要清理。正在用嵌套表格來佈局嗎?仍是爲了修復佈局問題而添了一堆的<div>
s?或許應該用更好的語義化標記。
YUI CSS utilities對佈局有很大幫助:grids.css針對總體佈局,fonts.css和reset.css能夠用來去除瀏覽器的默認格式。這是個開始清理和思考標記的好機會,例如只在語義上有意義的時候使用<div>
,而不是由於它可以渲染一個新行。
DOM元素的數量很容易測試,只須要在Firebug的控制檯裏輸入:
document.getElementsByTagName('*').length
分離組件能夠最大化並行下載,但要確保只用不超過2-4個域,由於存在DNS查找的代價。例如,能夠把HTML和動態內容部署在www.example.org
,而把靜態組件分離到static1.example.org
和static2.example.org
。
用iframe能夠把一個HTML文檔插入到父文檔裏,重要的是明白iframe是如何工做的並高效地使用它。
<iframe>
的優勢:
<iframe>
的缺點:
HTTP請求代價高昂,徹底沒有必要用一個HTTP請求去獲取一個無用的響應(好比404 Not Found),只會拖慢用戶體驗而沒有任何好處。
有些站點用的是有幫助的404——「你的意思是xxx?」,這樣作有利於用戶體驗,,但也浪費了服務器資源(好比數據庫等等)。最糟糕的是連接到的外部JavaScript有錯誤並且結果是404。首先,這種下載將阻塞並行下載。其次,瀏覽器會試圖解析404響應體,由於它是JavaScript代碼,須要找出其中可用的部分。
用CSS表達式動態設置CSS屬性,是一種強大又危險的方式。從IE5開始支持,但從IE8起就不推薦使用了。例如,能夠用CSS表達式把背景顏色設置成按小時交替的:
background-color: expression( (new Date()).getHours()%2 ? "#B8D4FF" : "#F08A00" );
前面提到了一個最佳實踐:爲了實現逐步渲染,CSS應該放在頂部。
在IE中用@import
與在底部用<link>
效果同樣,因此最好不要用它。
IE專有的AlphaImageLoader
濾鏡能夠用來修復IE7以前的版本中半透明PNG圖片的問題。在圖片加載過程當中,這個濾鏡會阻塞渲染,卡住瀏覽器,還會增長內存消耗並且是被應用到每一個元素的,而不是每一個圖片,因此會存在一大堆問題。
最好的方法是乾脆不要用AlphaImageLoader
,而優雅地降級到用在IE中支持性很好的PNG8圖片來代替。若是非要用AlphaImageLoader
,應該用下劃線hack:_filter
來避免影響IE7及更高版本的用戶。
把樣式表放到文檔的HEAD部分能讓頁面看起來加載地更快。這是由於把樣式表放在head裏能讓頁面逐步渲染。
頁面含有重複的腳本文件會影響性能,這可能和你想象的不同。在對美國前10大web站點的評審中,發現只有2個站點含有重複腳本。兩個主要緣由增長了在單一頁面中出現重複腳本的概率:團隊大小和腳本數量。在這種狀況下,重複腳本會建立沒必要要的HTTP請求,執行無用的JavaScript代碼,而影響頁面性能。
IE會產生沒必要要的HTTP請求,而Firefox不會。在IE中,若是一個不可緩存的外部腳本被頁面引入了兩次,它會在頁面加載時產生兩個HTTP請求。即便腳本是可緩存的,在用戶從新加載頁面時也會產生額外的HTTP請求。
用JavaScript訪問DOM元素是很慢的,因此,爲了讓頁面反應更迅速,應該:
有時候感受頁面反映不夠靈敏,是由於有太多頻繁執行的事件處理器被添加到了DOM樹的不一樣元素上,這就是推薦使用事件委託的緣由。若是一個div
裏面有10個按鈕,應該只給div容器添加一個事件處理器,而不是給每一個按鈕都添加一個。事件可以冒泡,因此能夠捕獲事件並得知哪一個按鈕是事件源。
腳本會阻塞並行下載,HTTP/1.1官方文檔建議瀏覽器每一個主機名下並行下載的組件數不要超過兩個,若是圖片來自多個主機名,並行下載的數量就能夠超過兩個。若是腳本正在下載,瀏覽器就不開始任何其它下載任務,即便是在不一樣主機名下的。
不少性能原則都是關於如何管理外部組件的,然而,在這些顧慮出現以前你應該問一個更基礎的問題:應該把JavaScript和CSS放到外部文件中仍是直接寫在頁面裏?
實際上,用外部文件可讓頁面更快,由於JavaScript和CSS文件會被緩存在瀏覽器。HTML文檔中的行內JavaScript和CSS在每次請求該HTML文檔的時候都會從新下載。這樣作減小了所需的HTTP請求數,但增長了HTML文檔的大小。另外一方面,若是JavaScript和CSS在外部文件中,而且已經被瀏覽器緩存起來了,那麼咱們就成功地把HTML文檔變小了,並且尚未增長HTTP請求數。
壓縮具體來講就是從代碼中去除沒必要要的字符以減小大小,從而提高加載速度。代碼最小化就是去掉全部註釋和沒必要要的空白字符(空格,換行和tab)。在JavaScript中這樣作可以提升響應性能,由於要下載的文件變小了。兩個最經常使用的JavaScript代碼壓縮工具是JSMin和YUI Compressor,YUI compressor還能夠壓縮CSS。
混淆是一種可選的源碼優化措施,要比壓縮更復雜,因此混淆過程也更容易產生bug。在對美國前十的網站調查中,壓縮能夠縮小21%,而混淆能縮小25%。雖然混淆的縮小程度更高,但比壓縮風險更大。
不要由於在HTML中能夠設置寬高而使用本不須要的大圖。若是須要
<img width="100" height="100" src="mycat.jpg" alt="My Cat" />
那麼圖片自己(mycat.jpg)應該是100x100px的,而不是去縮小500x500px的圖片。
favicon.ico是放在服務器根目錄的圖片,它會帶來一堆麻煩,由於即使你無論它,瀏覽器也會自動請求它,因此最好不要給一個404 Not Found
響應。並且只要在同一個服務器上,每次請求它時都會發送cookie,此外這個圖片還會干擾下載順序,例如在IE中,當你在onload中請求額外組件時,將會先下載favicon。
因此爲了緩解favicon.ico的缺點,應該確保:
使用cookie的緣由有不少,好比受權和個性化。HTTP頭中cookie信息在web服務器和瀏覽器之間交換。重要的是保證cookie儘量的小,以最小化對用戶響應時間的影響。
當瀏覽器發送對靜態圖像的請求時,cookie也會一塊兒發送,而服務器根本不須要這些cookie。因此它們只會形成沒有意義的網絡通訊量,應該確保對靜態組件的請求不含cookie。能夠建立一個子域,把全部的靜態組件都部署在那兒。
若是域名是www.example.org
,能夠把靜態組件部署到static.example.org
。然而,若是已經在頂級域example.org
或者www.example.org
設置了cookie,那麼全部對static.example.org
的請求都會含有這些cookie。這時候能夠再買一個新域名,把全部的靜態組件部署上去,並保持這個新域名不含cookie。Yahoo!用的是yimg.com
,YouTube是ytimg.com
,Amazon是images-amazon.com
等等。
把靜態組件部署在不含cookie的域下還有一個好處是有些代理可能會拒絕緩存帶cookie的組件。有一點須要注意:若是不知道應該用example.org仍是www.example.org做爲主頁,能夠考慮一下cookie的影響。省略www的話,就只能把cookie寫到*.example.org
,因此由於性能緣由最好用www子域,而且把cookie寫到這個子域下。
這個限制是由於iPhone不能緩存大於25K的組件,注意這裏指的是未壓縮的大小。這就是爲何縮減內容自己也很重要,由於單純的gzip可能不夠。
把各個組件打包成一個像有附件的電子郵件同樣的複合文檔裏,能夠用一個HTTP請求獲取多個組件(記住一點:HTTP請求是代價高昂的)。用這種方式的時候,要先檢查用戶代理是否支持(iPhone就不支持)。
前端工程師能夠想辦法明顯地縮短經過網絡傳輸HTTP請求和響應的時間。毫無疑問,終端用戶的帶寬速度,網絡服務商,對等交換點的距離等等,都是開發團隊所沒法控制的。但還有別的可以影響響應時間的因素,壓縮能夠經過減小HTTP響應的大小來縮短響應時間。
從HTTP/1.1開始,web客戶端就有了支持壓縮的Accept-Encoding HTTP請求頭。
Accept-Encoding: gzip, deflate
若是web服務器看到這個請求頭,它就會用客戶端列出的一種方式來壓縮響應。web服務器經過Content-Encoding相應頭來通知客戶端。
Content-Encoding: gzip
儘量多地用gzip壓縮可以給頁面減肥,這也是提高用戶體驗最簡單的方法。
Image with empty string src屬性是空字符串的圖片很常見,主要以兩種形式出現:
<img src=」」>
var img = new Image();
img.src = 「」;
這兩種形式都會引發相同的問題:瀏覽器會向服務器發送另外一個請求。
實體標籤(ETags),是服務器和瀏覽器用來決定瀏覽器緩存中組件與源服務器中的組件是否匹配的一種機制(「實體」也就是組件:圖片,腳本,樣式表等等)。添加ETags能夠提供一種實體驗證機制,比最後修改日期更加靈活。一個ETag是一個字符串,做爲一個組件某一具體版本的惟一標識符。惟一的格式約束是字符串必須用引號括起來,源服務器用相應頭中的ETag
來指定組件的ETag:
HTTP/1.1 200 OK
Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT
ETag: "10c24bc-4ab-457e1c1f"
Content-Length: 12195
而後,若是瀏覽器必須驗證一個組件,它用If-None-Match
請求頭來把ETag傳回源服務器。若是ETags匹配成功,會返回一個304狀態碼,這樣就減小了12195個字節的響應體。
GET /i/yahoo.gif HTTP/1.1 Host: us.yimg.com If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT If-None-Match: "10c24bc-4ab-457e1c1f" HTTP/1.1 304 Not Modified
Yahoo!郵箱團隊發現使用XMLHttpRequest
時,瀏覽器的POST請求是經過一個兩步的過程來實現的:先發送HTTP頭,在發送數據。因此最好用GET請求,它只須要發送一個TCP報文(除非cookie特別多)。IE的URL長度最大值是2K,因此若是要發送的數據超過2K就沒法使用GET了。
POST請求的一個有趣的反作用是實際上沒有發送任何數據,就像GET請求同樣。正如HTTP說明文檔中描述的,GET請求是用來檢索信息的。因此它的語義只是用GET請求來請求數據,而不是用來發送須要存儲到服務器的數據。
當用戶請求一個頁面時,服務器須要用大約200到500毫秒來組裝HTML頁面,在這期間,瀏覽器閒等着數據到達。PHP中有一個flush()函數,容許給瀏覽器發送一部分已經準備完畢的HTML響應,以便瀏覽器能夠在後臺準備剩餘部分的同時開始獲取組件,好處主要體如今很忙的後臺或者很「輕」的前端頁面上(P.S. 也就是說,響應時耗主要在後臺方面時最能體現優點)。
較理想的清空緩衝區的位置是HEAD後面,由於HTML的HEAD部分一般更容易生成,而且容許引入任何CSS和JavaScript文件,這樣就可讓瀏覽器在後臺還在處理的時候就開始並行獲取組件。
例如:
... <!-- css, js --> </head> <?php flush(); ?> <body> ... <!-- content -->
用戶與服務器的物理距離對響應時間也有影響。把內容部署在多個地理位置分散的服務器上能讓用戶更快地載入頁面。但具體要怎麼作呢?
實現內容在地理位置上分散的第一步是:不要嘗試去從新設計你的web應用程序來適應分佈式結構。這取決於應用程序,改變結構可能包括一些讓人望而生畏的任務,好比同步會話狀態和跨服務器複製數據庫事務(翻譯可能不許確)。縮短用戶和內容之間距離的提議可能被推遲,或者根本不可能經過,就是由於這個難題。
記住終端用戶80%到90%的響應時間都花在下載頁面組件上了:圖片,樣式,腳本,Flash等等,這是業績黃金法則。最好先分散靜態內容,而不是一開始就從新設計應用程序結構。這不只可以大大減小響應時間,還更容易表現出CDN的功勞。
內容分發網絡(CDN)是一組分散在不一樣地理位置的web服務器,用來給用戶更高效地發送內容。典型地,選擇用來發送內容的服務器是基於網絡距離的衡量標準的。例如:選跳數(hop)最少的或者響應時間最快的服務器。
這條規則有兩個方面:
Expires
來實現永不失效Cache-Control
HTTP頭來讓瀏覽器進行條件性的請求網頁設計愈來愈豐富,這意味着頁面裏有更多的腳本,圖片和Flash。站點的新訪客可能仍是不得不提交幾個HTTP請求,但經過使用有效期能讓組件變得可緩存,這避免了在接下來的瀏覽過程當中沒必要要的HTTP請求。有效期HTTP頭一般被用在圖片上,但它們應該用在全部組件上,包括腳本、樣式和Flash組件。
瀏覽器(和代理)用緩存來減小HTTP請求的數目和大小,讓頁面可以更快加載。web服務器經過有效期HTTP響應頭來告訴客戶端,頁面的各個組件應該被緩存多久。用一個遙遠的未來時間作有效期,告訴瀏覽器這個響應在2010年4月15日前不會改變。
Expires: Thu, 15 Apr 2010 20:00:00 GMT
若是你用的是Apache服務器,用ExpiresDefault指令來設置相對於當前日期的有效期。下面的例子設置了從請求時間起10年的有效期:
ExpiresDefault "access plus 10 years"
雅虎軍規參考地址:http://www.cnblogs.com/xianyulaodi/p/5755079.html
頁面重繪和迴流以及優化:http://www.css88.com/archives/4996