從微博的改版談網(wǎng)頁重構(gòu)——bigpipe中的頁面構(gòu)建優(yōu)化
![](http://image.woshipm.com/wp-files/img/58.jpg)
題記:搞互聯(lián)網(wǎng)的同學(xué)也許都知道一個數(shù)字——4秒,有研究表明,如果一個網(wǎng)站沒有在4秒之內(nèi)加載完成,用戶就會感到焦躁不愉快,并離開這個網(wǎng)站(數(shù)據(jù)來自性能測試網(wǎng)站http://gtmetrix.com/)。網(wǎng)站的內(nèi)容、SEO優(yōu)化、用戶體驗?哪個更重要呢?在速度面前,也許這些都相對更次要。所以提高網(wǎng)頁效率,是我們在新版微博的第一目標。從四個方面來淺談我們新版微博的優(yōu)化。
一、HTTP請求數(shù)的權(quán)衡
1、為什么要關(guān)心http請求?
當瀏覽器向Web服務(wù)器發(fā)出請求時,它向服務(wù)器傳遞了一個數(shù)據(jù)塊,也就是請求信息。在用戶打開一個頁面的初初,包括等待時間、請求時間、建立響應(yīng)時間、渲染時間……,都是消耗在前端的。比如下載圖片、下載樣式表、JavaScript腳本、flash等文件。大家應(yīng)該都經(jīng)歷過那個“多圖殺貓”的時代,加載那樣一個網(wǎng)頁會花費大量的時間。減少這些資源文件的請求數(shù)將是提高網(wǎng)頁顯示效率的重點。
假設(shè)用戶家的網(wǎng)速是10Mbps,10Mbps=10/8=1.25MB/s,那么他打開一個網(wǎng)頁時,如果網(wǎng)頁文件小于1.25MB,理論上他可以在一秒之內(nèi)打開網(wǎng)頁。下載網(wǎng)頁的快慢在顯示速度上占了很大比重,所以,網(wǎng)頁本身體積越小,瀏覽速度就會越快。這就需要產(chǎn)品、交互、設(shè)計,從最初就遵循盡量精簡的原則。
現(xiàn)在,就揭開新版微博的面紗,看看微博3.0和新版微博的區(qū)別吧。
微博3.0截圖
新版微博截圖
微博3.0是大家熟悉的兩欄結(jié)構(gòu),總寬為800px,有一級導(dǎo)航和二級導(dǎo)航、發(fā)布框、feed區(qū)、個人簡介區(qū)。新版微博是現(xiàn)在最流行的三欄式布局,總寬950px,除以前的內(nèi)容一個都不少之外,還整合出了左側(cè)導(dǎo)航和右側(cè)各種引導(dǎo)和公告。所以從理論上講,雖然內(nèi)容更豐富了,但新版微博著實比微博3.0的頁面體積大了很多。
2、什么是bigpipe?
網(wǎng)上有個例子舉得好:在飯館點菜吃的時候,如果點了四個菜,廚師沒有必要把四個菜一起炒好再上來。微博3.0就是這種把所有菜都炒好再上桌的網(wǎng)頁加載模式。所以用戶吃上菜的時候,已經(jīng)是第5秒了。現(xiàn)在新版微博的bigpipe網(wǎng)頁加載模式,是炒好一個菜先一個菜,用戶可以先吃著,廚師再炒第二個菜。甚至可以幾個菜并發(fā)同時炒。所以用戶吃上第一口菜的時間可能是第1秒,比之前提前了很多。
bigpipe模式示意圖
JS工程師把頁面分割成若干個小塊(pagelet),模塊彼此獨立,把html語言轉(zhuǎn)變?yōu)镴S語言,再把CSS通過style的方式加載進這段代碼,而不需要用以往的頭部link css地址的方式取樣式。每個模塊有自己對應(yīng)的html、CSS、JS,一旦開始運行模塊,就會尋找到對應(yīng)的CSS,并顯示對應(yīng)innerHTML內(nèi)容插入到對應(yīng)的html元素中,同時渲染出本模塊效果。比如執(zhí)行到feed區(qū)域的 id=”pl_content_homeFeed”時,樣式表只調(diào)用了feed.css。
3、為什么新版微博 CSS的HTTP請求數(shù)不降反增?
通過上面說的這種模式,css被全部link到頭部,是為了給后臺代碼提供出pagelet所需要的樣式列表。以前微博3.0頭部只link了3個CSS,新版微博首頁頭部卻需要link10多個css。雖然加載文件多了,新版微博CSS加載請求數(shù)反而高于v3,看似yslow降級了(這個數(shù)據(jù)已經(jīng)不能說明任何問題了)。但實際上新版微博CSS沒有像以往一樣合并起來,而是用一個加載一個,CSS和JS被分配到不同流水線中,模塊的加載變成并行的,先執(zhí)行完的模塊先顯示出來。所以新版微博CSS渲染的總時間并不超過V3CSS渲染的總時間,速度反而快了很多,減少了視覺等待。
請求數(shù) | 總大小 | 加載時間 | |
V3 CSS | 3?個請求 | 76.3 KB | 8.53s |
V4 CSS | 24個請求 | 50.2KB | 6.08s |
上面這張表格,來自yslow的分析。我們通過把頁面切成細小模塊寫樣式的做法,雖然請求數(shù)比以前大了8倍,但總大小上直降20K。
將多個CSS合并的做法固然可以減少請求,但對上億用戶的微博頁面來說,完成合并也許會帶來5%速度的提升。但是如果按bigpipe模式,即使http請求數(shù)提高了,但是整體的速度也許是之前的50%。
二、對CSS的優(yōu)化處理
1、提取公用模塊或公用元素,并反復(fù)調(diào)用
如果用戶每次訪問微博首頁時,就重新下載讀取CSS文件。這就會造成給服務(wù)器帶來額外壓力且用戶重復(fù)讀取耗時。新版微博的做法是,把模塊分為全局級模塊和頁面級模塊,首頁是全站的核心,所有模塊都是重要且重復(fù)性高的,所以首頁的所以模塊都是全局級模塊。首頁所需要的CSS被整理成一個pl列表反饋給工程師,等待處理。而一些非公共的css模塊樣式被單獨寫在屬于本頁面的文件里,這樣就最大化的節(jié)省了文件大小及利用率。這么做還有一個好處,就是公共模塊樣式被調(diào)用過后,會在瀏覽器里留下緩存。調(diào)用最頻繁的模塊,反而樣式被最快的加載進來。
舉個簡單的例子:
.clearfix:after{content: “.”;display: block;height: 0;clear: both;visibility: hidden;}
.clearfix {display: inline-block;}
這是一段全局代碼,基本上每個頁面都會用到這個類,我們就沒必要把這句寫在每個網(wǎng)頁的CSS里面,只把它提取到base.css里,并方便進行皮膚管理。
又比如,首頁右側(cè)欄有個“可能感興趣的活動”類似的模塊都是采用獨立的div容器,這個段落的詳細代碼,如果寫在公用CSS文件里,肯定就浪費了。
2、盡可能少的使用css images
能通過代碼或字符實現(xiàn)的,就不用圖片去解決。比如“可能感興趣的人”展開氣泡上下三角、返回頂部的箭頭、“更多”后面的?符號等。既減小CSS圖片請求,又不會面臨若干套皮膚升級困難的問題,僅通過對CSS的color、backgroud等屬性的控制,就可以換色了。
可以看看按這個做法之后明顯的優(yōu)勢,下圖來自yslow的statistics。微博3.0的css image總大小為970.1K,新版微博的css image總大小為693.9K,總量直降30%。
微博3.0 statistics
新版微博 statistics
3、盡量使用CSS3等新技術(shù)
在新版微博里,我們制定了使用CSS3的原則,即非圖片類的元素效果圖,如圓角、陰影、漸變、半透等效果,可以通過樣式控制,而無需切圖的元素,在得到設(shè)計師認可后,不用圖片,只做樣式控制。滿足高級瀏覽器的視覺,ie系列不能顯示的,有原則的放棄。不僅為速度助力,還在放棄低級瀏覽器的大方向前進一步。
4、鼠標滑上效果改用偽類實現(xiàn)
在逐步放棄ie6的事情上,新版微博已經(jīng)盡最大的努力做了。為了保證各瀏覽器的完全兼容,微博3.0以前我們曾經(jīng)放棄讓CSS實現(xiàn)鼠標滑上效果,而由JS控制。隨著ie6使用率的日益降低,新版微博又一大革新就是重新使用偽類,僅通過CSS就實現(xiàn)的瀏覽器原生效果,不僅計算速度比計算一個JS快得多,也終于放棄了低端的ie6。
舉個評論頁feed區(qū)的例子:
CSS代碼如下:
每個單條feed在鼠標滑上時,都會顯示舉報和刪除鏈接。這是交互設(shè)計出于對頁面呈現(xiàn)內(nèi)容的視覺舒適感所做的設(shè)計,我們通過對塊元素直接寫偽類,實現(xiàn)這個效果,不需要再通過JS了。ie6呢?就讓它一直擺著去吧。
三、對dom結(jié)構(gòu)的優(yōu)化處理
1、bigpipe模式重構(gòu)并優(yōu)化垃圾代碼
v2從v1來,v3從v2來,在v3不堪重負的時候,新版微博的代碼優(yōu)化誓在必行了。所以我們并沒有沿用之前的結(jié)構(gòu)和CSS,而是直接推翻v3,重構(gòu)新版微博。和JS工程師一起搭建的bigpipe模式,把頁面分成細小的塊,每一個模塊對應(yīng)一個CSS。代碼寫到最優(yōu),結(jié)構(gòu)和樣式完全分離,并杜絕內(nèi)聯(lián)調(diào)用的方式。下圖示意了我們用模塊配頁面的最終效果,模塊可以被細分為如此程度。模塊拆的細,復(fù)用性被提高。
2、盡量減少代碼體積
由于代碼行數(shù)越少體積就越小,所以我們這次想辦法減少網(wǎng)頁代碼的行數(shù)。相同或類似的模塊,說服設(shè)計師把視覺規(guī)范統(tǒng)一。我們只通過對CSS補丁,覆蓋原樣式,并不改變頁面的dom結(jié)構(gòu),直接降低重復(fù)代碼率。舉個例子,“我的首頁”和“我的profile頁”,同樣是有feed區(qū)域的,區(qū)別是但一個有頭像,一個沒有頭像。只需要一套feed.css代碼,然后在“我的profile頁”獨立的頁面級CSS中,打個去掉頭像的補丁即可。
3、首頁中杜絕Table布局和iframe
杜絕首頁中出現(xiàn)Table布局。因為傳統(tǒng)的table布局,是把內(nèi)容全部加載完成后,才渲染樣式,延遲效果嚴重。而iframe頁面框架,是非語義的,即使為空也會有較大資源消耗,還會阻止頁面的onload。
四、對圖片的優(yōu)化處理
1、圖片的存儲格式
我們改變了v3的做法,把icon類小圖片或背景類圖片,由以前的gif存儲盡可能多的轉(zhuǎn)為png8的存儲,這是個減小圖片體積的好辦法。Png8有g(shù)if的所有特點,但是相比gif,png8的優(yōu)勢是alpha透明和更優(yōu)的壓縮。png24全透明的圖片,只給支持的瀏覽器使用,ie6在不影響視覺的前提下,改為gif呈現(xiàn)。我們還會利用的圖片優(yōu)化工具處理圖片,保證效果但卻降低文件大小。下圖是主鍵類頁面的images文件夾示意圖,除必須獨立的icon外,png類型的圖片比重大得多。這在之前的V3并沒有做到。
2、css sprites
在圖片的拼合方面,我們是持之以恒這么做的。在v3里,我們把所有首頁和profile頁里出現(xiàn)的背景類圖片都拼合到一張大圖上,新版微博比之前高明在,我們把放置文件夾細分。假設(shè)我們把公用型放入common,頁面類放入index,換膚類放入skin。把sprites拆分的更細,盡可能在加載首頁時,減少圖片請求數(shù)。
3、大圖片、小圖片
對于大背景圖,我們的做法是不分割成小區(qū)塊兒的。首先的因為,原本一個圖片的請求數(shù)會變成多個。另外,大約80%以上調(diào)用圖片所消耗的時間,是用來檢索緩存和確定鏈接是否有效的阻塞時間。也就是說,如果把一個大圖片,切成若干小圖片,雖然解決了圖片的加載時間,卻花費了更多的阻塞時間。
4、在已知寬高的圖片標簽內(nèi),直接指定寬高。
Feed區(qū)域里頭像需求是50*50的,所以后臺直接吐出這個尺寸的圖片。在已知寬高的情況的,我們在img標簽中直接指定了height和width參數(shù)。因為如果瀏覽器沒有找到這兩個參數(shù),它需要一邊下載圖片一邊計算大小,首頁有多少條feed就有多少個頭像,瀏覽器需要不斷地調(diào)整計算。當瀏覽器知道了height和width參數(shù)后,即使圖片暫時無法顯示,頁面上也會預(yù)留空位,繼續(xù)加載后面的內(nèi)容。
新版上線后,不少公測用戶的反饋速度變快了,微博瀏覽起來更順暢了。這不是我們頁面重構(gòu)組的功勞,是整個微博團隊,或者說是bigpipe思想的功勞。但“速度快了”這句話本身,就是對我們團隊工作最好的褒獎,對我們參與開發(fā)的團隊成員的最好的鼓勵。抓住產(chǎn)品改版的機會,就是自己對優(yōu)化的研究和經(jīng)驗的積累落實到細節(jié)的機會。雖然還任重道遠。
來源:http://blog.sina.com.cn/s/blog_482611850100xpb1.html
- 目前還沒評論,等你發(fā)揮!