萬盛學電腦網

 萬盛學電腦網 >> 網頁制作 >> 交互設計 >> 5173首頁前端性能優化實踐

5173首頁前端性能優化實踐

  從制定計劃,到前後端的開發,最後到測試以及上線,歷時4個月,5173首頁前端性能優化項目終於順利上線,並達到了預期的性能優化目標。這次的項目並不是改版,而是原來首頁的設計和功能不變,只做重構和優化。雖然項目名叫前端的性能優化,但也並不僅僅是前端單方面的工作,要想徹底的把優化做好,就需要前後端的通力配合。

  歷史背景

  老首頁應該是09年上線的,首頁也是各部門爭奪資源的地方,大家都想在首頁有一席之地,各部門在首頁都有各自的小豆腐塊,如果有新項目的上線,大多是打補丁的方式,並且唯一的規范就是能保證功能正常運行,至於性能方面,那是很遙遠的事。苦逼的是開發人員,每次有首頁的修改都是擔驚受怕的,怕改了這個那個又出問題,歷史原因造成的問題越來越多。

  最先看不下去的應該是前端人員,因為首頁在不斷的修修補補中,性能已經差到前端人員覺得很沒面子的地步了。但是看不下去也僅僅是看不下去,沒法采取實質性的措施來改善,因為這牽涉到各部門的利益,也如上面說的,優化不僅僅在於前端,於是前端人員也只能向上面反映問題。到了今年,終於領導也看不下去了,某領導在海外訪問我司的818.com和5173.com首頁,對比起來前者首頁很快(插播一句,818首頁前端開發人員也正是我^_^),後者首頁很慢,差別較大。於是在領導重視的推動下,5173首頁的前端性能優化項目才經過批准,開發人員終於可以放手大膽的折騰了。

  問題分析

  在動手前要制定計劃,制定計劃要從解決實際問題出發,先來看看老首頁的問題,這是我在制定計劃時收集的相關數據:

  1、請求數過多,其中CSS外鏈數有12個,JavaScript外鏈數竟有41個;

  2、頁面總體積過大,很多靜態資源都沒加gzip,動態站點的JS甚至都沒有壓縮過;

  3、資源占用嚴重,在IE6下滾動頁面時CPU占用率高達80%以上,內存洩漏也很嚴重;

  4、廣告系統,廣告圖片都是以document.write的方式在加載,頁面堵塞的情況很嚴重;

  5、頁面有7個iframe;

  6、數據源接口混亂;

  7、頁面加載速度過慢,有白屏現象,首屏完成加載很慢;

  上面的數據讓你很震驚,這也說明了有很大的優化空間。找出了問題所在,接下來才有具體的實施方向。總之,無論是常規的方法,亦或是奇淫技巧,目標只有三個字,“快,更快”。

  具體實施

  雖然粗看頁面的內容並不是很多,但是具體到功能模塊,都是很費時費力的。我們老大有一句很經典的話,“通常我會問面試人員一個問題,如果你獨自來做5173首頁的前端工作,多久能完成?如果答案只有一個星期,要麼是沒看過頁面,要麼就是很不專業。”我就獨自花了一個多月的時間才完成首頁的前端開發工作。下面來說說具體的實施吧。

  HTML&CSS 的重構

  頁面的設計和功能沒有變動,但是HTML頁面還是要做徹底的重構,這裡我也嘗試了使用 HTML5 的新標簽來對頁面進行布局。CSS 的重構也是理所當然的,原來有12個外鏈的 CSS,這些都要統統干掉的,有些模塊如果不止首頁有用到,就需要模塊化,該放到公用文件就放到公用文件中,在開發的時候可以分多個模塊,然後使用 @import到一個文件中,打包發布的時候再合並成一個文件。這需要把握好一個度,即要合理利用緩存,又要避免單文件過大,同時也要做好模塊化。

  老首頁有很多 CSS 選擇器過長的問題,可能一個 CSS 選擇器的組合長達6-7個也是常有的事,CSS 選擇器過長不僅僅是性能方面的影響,同時也因為 CSS 權值的關系,給後期維護帶來了很多的麻煩。應該多使用 class 來定義選擇器,再加上 tag 選擇器的組合,最多3個選擇器的組合就能滿足絕大多數的需求了,另外在 CSS 的編寫方面禁止使用 id 選擇器和 !important,養成良好的 CSS 編寫習慣很重要。

  JavaScript 的重構

  JavaScript的重構太迫切了,原來竟有41個 JavaScript 外鏈文件,當然這些外鏈也包括了15個廣告的外鏈,廣告的優化我稍後再說,但是還剩下26個外鏈 JavaScript。這些臃腫不堪的 JavaScript文件即是造成頁面加載堵塞的元凶,也是系統資源占用的蛀蟲,這是整個項目的難點之一。

  重新梳理了四級聯動搜索的業務邏輯,並對四級聯動搜索的交互功能做優化,增強用戶體驗。這個模塊的 ajax 交互功能較多,最大的 JSON 數據包竟然有94.4KB,此時合理的利用當前頁面的緩存功能($.fn.data)很重要。體積最大的 JSON 數據包在頁面 Dom Ready 後進行加載,然後拼裝第一屏的 HTML 代碼並緩存,當用戶按字母索引選擇游戲的時候再到已加載完的 JSON 數據包中尋找相應的數據去拼裝 HTML 代碼,然後緩存該索引的 HTML 代碼。如果接下來再選擇區、服、交易類型時,再到服務器去取相應的 JSON 數據,拼裝成 HTML 代碼後進行緩存,此時只緩存最後一次的選擇結果。

5173首頁前端性能優化實踐 三聯教程

  便民中心也同樣是首頁業務邏輯很復雜的模塊,涉及到很多的ajax交互以及表單的操作。各個TAB中的表單是根據請求的JSON數據來生成HTML結構的,原來是每次點擊TAB都會請求一次數據,然後生成HTML結構,每切換一次TAB都要請求,再生成,這真得很二。同樣的數據和結構只要請求一次,並生成一次即可,這種重復的操作是赤裸裸的浪費資源。該模塊的JavaScript原來請求的動態站點的文件,沒有做緩存也沒做過壓縮,每次頁面加載都在這裡阻塞一小會。這裡的服務端的數據源接口也很亂,開發人員缺乏規范化數據接口的概念。這裡的諸多問題,我已無力吐槽了。最後也是重新梳理蛋痛的業務邏輯,重構代碼。

  延遲加載,提升首屏的加載速度

  當用戶打開一個很長的網頁時,首屏內容的加載給了最直觀的速度體驗。所以,讓首屏盡快的完成加載也是用戶衡量該頁面是否夠“快”的最主要的因素。5173的首頁,圖片基本都集中在下面的位置,讓下面的這些圖片全部都延遲加載就可以盡可能快的提升首屏的加載速度。常見的圖片延遲加載技術想必大家都不會陌生了,這裡就不復述。在 TAB 內容中也同樣有很多圖片,這裡也讓它們在觸發 TAB 菜單的時候再進行加載。給圖片在HTML代碼中添加固定的尺寸自然也不再話下。so easy? no!

  圖片中不僅僅有業務配置的圖片,也有來自第三方廣告系統的圖片(包括首屏的輪播大圖也是此類型的)。這些廣告圖片的 URL 是一個 JavaScript 鏈接,其中包含了使用 document.write 的方式來加載廣告圖片的代碼。還有些 TAB 中包含了使用 iframe 嵌入到頁面的合作站點的內容。廣告圖片以及 iframe 都是阻塞頁面加載的元凶。

  最初的想法是重新開發一套廣告系統,換一種廣告加載方式,但是開發成本太高。最後想到了使用 textarea 來延遲加載廣告和 iframe,玉伯提供的這種方法確實挺好用的。textarae 是個好東西,不論是普通的 HTML 代碼亦或是 CSS、JavaScript 代碼,都可以扔到裡面去實現延遲加載。廣告圖片的優化比較麻煩,我在另一篇文章中有詳細的介紹。有了 textarea,很多內容都可以像實現圖片延遲加載那樣來實行延遲加載,在 TAB 內容中的 iframe 也可以在觸發 TAB 菜單時再去加載 iframe。

  正是這些各種延遲加載內容的奇淫技巧在最大限度上提升了網頁首屏的加載速度。但是延遲加載內容帶來的副作用需要說明,對於一些比較重要的內容,需要考慮到對 SEO 的影響。

  服務端的優化

  前端能做得基本都說完了,再來說說服務端的優化工作吧。原來服務端提供給前端的數據源都是從各個站點過來的,前端需要跟各個部門的開發人員打交道,並且他們提供的數據源在性能上也比較慢。經過協商決定將各數據源匯總到一台中間服務器上,前端統一從這台中間服務器中去取數據,服務器端之間的通訊都加上一定的緩存時間,這樣就解決了數據源慢和不統一的問題。

  針對頁面總體積過大的問題,代碼的重構確實能減小不少的體積,另外靜態資源一律都要添加gzip,僅僅是添加gzip,帶來的性能提升也是比較明顯的。

  合理的利用浏覽器端的緩存也是很重要的,除了登錄信息以及 cookie 的這種時效性較高的請求外,所有能添加 cache-control 的請求都加上了 max-age 的過期時間。關於浏覽器端的緩存添加,這裡有一篇比較詳細的文章 Cache them if you can。緩存的添加也會給更新帶來麻煩,所以要有相應的方法來清除緩存,給靜態資源的請求加上時間戳即可。

  另外服務端這次也大膽的采用了 varnish 作為緩存加速服務器,這在國內大型網站中應該還不多見。

  優化成果

  做了這麼多工作是時候看看優化成果了,先來看一組數據對比:

  優化前後的請求數對比:

  請求數的大大減少,緩解了服務器的壓力,可以撤掉很多服務器了。

  優化前後的靜態資源的文件體積對比,沒有包含ajax數據等其他文件體積:

  從文件體積的對比來看,優化後節省了494KB的下載量,假若按照日PV1000000(估值,實際值遠

copyright © 萬盛學電腦網 all rights reserved