隨著互聯(lián)網(wǎng)的發(fā)展,尤其是在2000年之后瀏覽器技術漸漸成熟,Web產品也越來越豐富,這時我們被瀏覽器窗口內的豐富“內容”所吸引,關注HTML/CSS,深入研究Dom、Bom和瀏覽器的渲染機制等,接觸JavaScript庫,“前端”這個職業(yè),由此而生。
前端技術在這10多年中飛速發(fā)展,到了今天,我們可能發(fā)現(xiàn)“內容”的美在視覺上是有上限的,而性能的追求卻是無窮無盡的,前端優(yōu)化的重要性慢慢被前端工程師們發(fā)現(xiàn),尤其是在如今火熱的大型電子商務網(wǎng)站技術架構中,前端優(yōu)化一定是一項必不可少的工作,今天就給大家?guī)眄権S旗下的跨境電商平臺——豐趣海淘的前端性能優(yōu)化之路。
為什么需要前端性能優(yōu)化
我們都知道在瀏覽器訪問一個網(wǎng)站時,有10%-20%的時間是花在下載HTML上,其他80%-90%時間是花在下載頁面中所有組件上。如果我們把后端時間縮短一半,整體響應時間可能只會縮短5%-10%。然而我們花同樣的精力關注前端的話,我們能將響應時間縮短到一半之多,這樣的提升可想而知。
可能上面的描述比較抽象,我們來看一些研究的數(shù)據(jù):
· Amaon 慢 0.1s會導致1%的用戶放棄交易
· Google 慢 0.4s會導致0.6%的用戶放棄搜索
· Yahoo! 慢 0.4s會導致減少 5%-9% 的流量
· Bing 慢 2s會導致收入下降 4.3 %
如果將這些數(shù)據(jù)換算成金錢上的話,那將是一筆無法估量的損失,前端優(yōu)化勢在必行。
怎么樣才算足夠快
對于豐趣海淘來說,考察前端性能的參考指標一般有兩個:一、首頁加載時間;二、頁面大小。頁面大小方面每次新版迭代時候通過測試人員去檢測,加載時間就需要使用第三方監(jiān)測工具去監(jiān)測實際用戶加載時間。
這些指標具體到實際使用中分為三個層次:
· 0.1秒:用戶直接操作ui中對象的感覺極限。例如,用戶直接選擇表格的一列到該列高亮顯示,或者反饋被選擇的時間間隔。
· 1秒:用戶隨意在計算機指令空間操作而無需過度等等時間的感覺極限。0.2-1.0的時間延遲會被用戶注意到,會讓用感覺到計算機正在對指令進行處理中。等待的時間過長,會讓用戶失去流暢的體驗。
· 10秒:用戶專注于任務的極限,超過10秒的任何操作都要有一個進度指示器,以及有一個讓用戶中斷操作,而且有清晰的標示方法。假設用戶超過10秒后返回界面,他們將要重新適應。
換句話說執(zhí)行如果超過0.1秒,會讓人感覺到不平滑。如果超過1秒會讓人感覺應用程序緩慢;超過10秒那么用戶會非常沮喪。這些就是用于足夠快的標準。
開始優(yōu)化之前
在知道了優(yōu)化的好處和標準以后先來看看豐趣海淘的架構。在制定網(wǎng)站的整體框架時候,豐趣海淘強調架構的上的前后端分離,這種分離意味著數(shù)據(jù)層、復雜業(yè)務邏輯與前端展現(xiàn)和交互的層次分離,這樣做有很多好處:
1、在開發(fā)和分工上面可以分得清楚,對并行開發(fā)有很好的效率提升,不被對方所綁架。在開發(fā)時,通過事先的約定,前端和后端可以同步進行。而交接層通過單元測試保證交付,可以縮短項目進度。
2、結構清晰,前端后端分得較為清楚,所有的后端服務都會通過一個統(tǒng)一的網(wǎng)關,通過HTTPS的方式把數(shù)據(jù)通過接口的方式暴露出來,大部分的頁面是在前端完成比較輕的邏輯,從這個角度來講,不管是前端的WEB還是H5頁面還是移動的客戶端,共享的都是同一套后端服務的接口。流動的數(shù)據(jù),讓前后端可以獨立的專注的做自己,而不是被對方所綁架。
豐趣海淘優(yōu)化之路
1、詳情頁優(yōu)化
豐趣海淘的詳情頁采用服務端渲染加客戶端渲染兩種相結合的方式,服務端負責突出基本信息和圖文說明,而客戶端負責進行熱數(shù)據(jù)的再次請求和熱數(shù)據(jù)的渲染。
優(yōu)化之前,詳情頁的主文件行數(shù)已經達到2.5k,同時因為每次大促因為涌入大量流量,導致詳情頁的加載非常慢,所以優(yōu)化旨在承擔代碼重構和性能優(yōu)化兩份責任。
A.代碼重構
豐趣的詳情頁主要有如下幾部分組成:商品信息、推薦商品、評價信息、最近瀏覽等。其中商品信息中包含價格信息和購買區(qū)域等等。為了減輕主文件的復雜度以及配合后面提及的性能優(yōu)化,這里特對分出四大組件:推薦商品組件、評價組件、最近瀏覽組件和活動組件,這幾個文件相互獨立渲染。在后面的組件懶加載中會進行詳細說明。
詳情頁中最復雜的部分就是活動。不同活動展示的價格不同,購買按鈕也可能不同,當前豐趣的活動有秒殺、預售、搭配購、限時促銷等等,另外還有倒計時配合各個活動。如果不采用活動隔離的方案,那將會產生大量的if else,造成代碼難以插腳。
針對這個問題,分離出了秒殺、預售、搭配購、限時促銷等活動類,同時抽取了一個活動父類供他們繼承。
當前已經拆分出來的活動類:
價格、購買區(qū)域組件引用繼承關系如下:
main為入囗,object為活動類父類,normal為普通的活動。其他活動類在類關系圖中不一一列出
這樣就做到了活動類的徹底解耦,后續(xù)增加活動只要新建一個文件即可。
B.性能優(yōu)化
B.1.組件懶加載
組件懶加載參應用于首頁和活動頁,因為這些頁面組件之間的關聯(lián)性較少,適合組件的懶加載。而詳情頁的組件之間有的是有關聯(lián)的,但是豐趣的這些關聯(lián)當前都是可以通過某種手段規(guī)避的,所以在詳情頁中也進行了組件懶加載的大膽嘗試。
前面提到,豐趣的詳情頁組要分出了四大組件:推薦商品組件、評價組件、最近瀏覽組件和活動組件。因為這些組件相對獨立,把推薦商品組件、評價組件和最近瀏覽組件定位成為懶加載組件,而活動組件因為在第一屏就要進行展示,所以沒有把它定義為懶加載組件。
所以這里就總結下
1、使用組件懶加載的目的:減少DOM節(jié)點和請求數(shù),以達到第一時間渲染出首屏供用戶使用。
2、什么樣的組件審核定義為懶加載組件:非首屏的組件才能定義為懶加載組件。當然有的組件和其他組件參少有點關聯(lián),這個關聯(lián)程度如果能夠通過代碼hack掉,那也是可以定義成懶加載組件的,這就看自己的權衡了。
現(xiàn)在來看下豐趣的懶加載組件設計。
懶加載組件定義:采用HTML標簽的方式,當前定義的組件是如下三個,推薦商品/評價/最近瀏覽。
懶加載組件支持的字段說明:
1、Id組件id:唯一標示
2、data-floor(預留 未使用)組件樓層:當滾動到1樓時,可以預先加載2樓的數(shù)據(jù)
3、data-positionid組件位置:組件實例化出來后放置的位置,用于移動組件位置
4、data-widget組件名稱:當前已經存在的組件
5、data-params組件參數(shù):用于給組件實例化使用
6、data-callback組件回調:用于組件實例化之后的回調
7、widgetlazyloaded是否已經加載:如果組件已經加載了,該屬性會被置為true,標示已經加載渲染過了,后面就不會重復渲染。
懶加載組件解析:我們定義了一個管理懶加載組件的類:vendor.widgetLazyLoad,該類能夠支持高優(yōu)先級和低優(yōu)先級兩種組件:高優(yōu)先級的組件是在滾動時候也進行加載,低優(yōu)先級的組件只有等滾動結束了才進行加載。
B.2.本地存儲
有些配置類接囗無需每次讀取接囗。當前接囗已經支持定義本地存儲,只需傳遞"throttleMode":true即可,默認存儲五分鐘,為安全起見,不支持配置時間。
接囗要求:必須是讀取配置類的接囗。當前已經支持的接囗只有兩個:b2cmall.getCmsHeaderConfig和search.getSearchHeaderConfigo。當然第一個接囗和第二個也不一樣,它是會根據(jù)不同頁面吐出來不同數(shù)據(jù),所以這個要做到頁面級別的存儲。
B.3.合并請求
前端頁面中,有很大一部分性能是耗在和服務端的接囗交互中的,特別是在大促期間,服務立巖因為大量請求的涌入處理速度會變慢,同事帶寬也會被占滿導致無法進入。如果此時前端還是一個接囗依賴一個接囗的和服務端進行交互,帶來的必然是用戶界面的不可用為了減少和服務端的請求交互,詳情頁中兩個負責讀取價格信息的重要接囗:活動活動信息和獲得價格信息(product.getActivityInfo,product.getProductHotData)已經合并為一個請求發(fā)送,后面簡稱activityData。
B.4.延遲加載
在詳情頁,獲得購物車數(shù)量和是否已經收藏該商品(getTotalCount和isCollectedGoods)優(yōu)先級比較低,在渲染價格后再加載,以保證讓用戶在第一時間可以購買商品。
2、前端速度優(yōu)化
就像上面我們提到的“足夠快”,訪問速度是用戶體驗的第一基準,圍繞著速度其實有很多可以做的地方,前端的提速首先需要縮短了資源下載的時間:
· 豐趣海淘在CDN方面選用的是阿里云CDN,目前所有的靜態(tài)資源都是在阿里云的CDN上, 其中包括JS。無論APP、HTML5頁面還是Web頁面,用戶在加載頁面的時候都能從最近的CDN節(jié)點下載靜態(tài)資源,從而起到加速效果。
· 豐趣海淘APP會用到的所有HTML5資源都會有緩存,緩存能夠比較好的提升用戶使用APP的體驗。
3、前端性能監(jiān)控
無論是大到整個系統(tǒng)架構設計,還是小到頁面大小,加載時間甚至CDN的使用情況,都需要一個監(jiān)督前端用戶體驗情況的工具,豐趣海淘選擇使用聽云Browser來進行日常的監(jiān)控工作,希望建立一個長效的機制反饋用戶的使用情況,好及時做出應對。
§ CDN監(jiān)控
采用了商業(yè)CDN的服務,但向來CDN服務質量不太透明,效果好壞無法判斷,之前偶爾有用戶反饋頁面打開緩慢的問題,然而自己去做監(jiān)測費力不討好,所以通過使用聽云Browser來幫助實時了解用戶在打開頁面過程中訪問到CDN內容的加載時間。我們通過對以往數(shù)據(jù)的對比,可以評估CDN在全國范圍內的服務質量,一旦發(fā)現(xiàn)加速效果不佳,可以及時與廠商溝通進行調優(yōu)。同時,結合聽云Network進行主動式監(jiān)測,還可以發(fā)現(xiàn)解析失敗、無法建連等網(wǎng)絡錯誤問題,對CDN服務做到全方位監(jiān)測,從而有效減少了網(wǎng)民的投訴數(shù)量。
§ 頁面加載時間監(jiān)控
作為一個電子商務網(wǎng)站,在行業(yè)競爭激烈的今天,用戶購物體驗的好壞直接關系訂單最終是否能夠成交。而在購物過程中,頁面的加載時間是非常重要的一個指標。通過使用聽云Browser,我們可以實時看到全國各地用戶頁面的加載時間更新,可以第一時間發(fā)現(xiàn)頁面加載緩慢的現(xiàn)象,并能追溯到具體某一次慢頁面打開的情況,這個對豐趣海淘來說是很重要的參考數(shù)據(jù)。
4、其他優(yōu)化
在此次優(yōu)化中,我們還做了其它優(yōu)化:
1.SVG文件由之前的直接貼在HTML中變成背景圖
2.HTML的壓縮
優(yōu)化結果
文件結構與發(fā)送請求數(shù):
頁面性能:
下面是優(yōu)化前后的數(shù)據(jù)對比,采用10個詳情頁平均性能的方式:
可以看到HTML大小、首屏前端時間和首屏時間都有明顯提升。
優(yōu)化之路沒有盡頭
從結果上來看,這一次的優(yōu)化是有很大效果的,但這樣優(yōu)化不是第一次也不是最后一次,未來豐趣海淘還會有更多的動作:
· 除去現(xiàn)在的靜態(tài)資源和JS,未來豐趣海淘還考慮將部分HTML頁面放到CDN上,這樣會有更快的瀏覽速度
· 考慮建立CDN的切換機制,已應對更多的用戶訪問需求
· 在監(jiān)控方面未來會考慮增加線上報警策略,更好的提醒我們運維人員去處理體驗上的缺陷
優(yōu)化的道路沒有終點,為了那永遠的“0.1”,豐趣海淘一直在路上。