前端工程與性能優化

1.0時代css

 

 

前期模塊化已經作的不錯了,至少沒必要花大量時間去重構代碼。模塊劃分以下圖,邏輯層次上仍是比較清晰。html

前端模塊化依賴的主流庫也就數國內的Seajs和國外的requirejs,這裏就不陳述。採用了Seajs做爲模塊管理器,zepto做爲基礎庫文件,lib主要包含了項目中用到的主流第三方庫文件。前端

咱們知道模塊化帶來的最大弊端即是HTTP請求數增長,因此上線的時候必須合併文件。下圖中的package模塊是文件大集合,打包了不少個JS模塊,除去上圖中的基礎庫文件和業務模塊層,在上線的時候大部分文件都被打包在package.js裏。node

大部分頁面的JS請求是這樣的:git

細心點的同窗可能注意到兩個問題:文件的大小和加載時間。剛纔的截圖仍是在PC端截取的,手機和不一樣網絡環境的表現會更加糟糕。github

如今來看下目錄 瀏覽器

存在的問題:

  • 目錄看起來算規範,但其實是公共的和業務的混在一塊。緩存

  • 大部分文件合併在一個文件,合併策略不合理。cookie

  • 由第二點引起的第三個問題,發佈上線時,只要兩人發佈涉及到package文件,衝突必然發生。網絡

  • 發佈時須要down下上一次的文件,對照合併的新文件,以避免發錯。

  • 注意,第四點是人工。一不當心發錯,或者把他人剛發佈的文件覆蓋了,這種事情發生10+次。

  • 只有一臺測試機器,測試環境常常覆蓋是常事。

  • 版本控制問題,不以SVN爲版本,而是預發佈機器上代碼,管理混亂

不敢想象若是10+人的團隊一塊兒在這種模式下開發,會是怎樣的場面。

 

22.0時代

 

由第一個版本引發的問題,着實讓人很蛋疼,每次開發版本就是一次陣痛,尤爲是測試、發佈環節。因此就開始慢慢着手解決。隨着業務擴展,人員增多,就誕生了下面這個圖。

優化措施:

  • 調整模塊,讓共用的模塊更加共用,業務模塊跟隨業務自身。

  • 更改模塊合併策略,既然大了,我就分紅小,必定程度緩解了衝突。

  • 替換原有的同步文件工具,包括測試與正式環境,接入ARS,提測發佈流程順暢多了。

  • ARS帶有衝突檢測功能,告別人工對照合併,覆蓋再也不容易發生。

  • 公共JS文件緩存在localstorage中,模擬manifest,帶版本號控制。

  • 以SVN爲板塊控制工具,再也不對照外網代碼。

一些統計

  • localstorage本地緩存

  • localstorage緩存命中率



  • 首屏時間

  •  

  • window.onload時間

一切看起來很美好,可是好景不長,由於新的問題又來了。

  1. 以前拆分package.js文件爲多個文件,實際請求的時候則是合併了請求,包括JS文件和CSS文件。combo文件實際上會有延遲問題,在發佈的時間節點上存在不一樣步的問題,直接致使頁面掛了。

  2. 拋開combo文件不說,因爲瀏覽器緩存的問題,每次更新版本的時候要手動加上一個時間戳,來規避緩存形成的錯誤。也是個很蛋疼的點。

  3. 隨着業務增加,愈來愈多頁面是放在APP裏面訪問。觸屏頁面已經再也不是重點,如何更好的利用APP加速頁面纔是關注點。不少人想到了手Q的離線包,但據說實踐起來也不是特別方便,咱們就採用了客戶端緩存hash文件的策略,告別304。因此這裏又涉及到自動化。

  4. 雪碧圖基本是手工;

  5. 代碼混淆沒有壓縮;

  6. CSS合併文件要手寫地址,相似下面:

http://at.qq.com/min/f=cssv4/common/reset.css,cssv4/common/base.css,cssv4/module/btns.css,cssv4/module/tab.css,cssv4/module/app-list.css,cssv4/module/talk-bar.css,cssv4/module/popup.css,cssv4/page/game-detail.css,cssv4/page/talk.css,cssv4/module/comments-bar.css

33.0時代

 

爲了解決上述問題,流程須要進一步優化,簡單點就是讓自動化程度更提升。

3.1 探索期

前期在方案選擇上也作過一些討論,本身徹底從底層寫時間上不容許。以前折騰過Grunt發現並非那麼好用,後來發現百度的前端解決方案FIS可以知足咱們的需求。

  1. 生成以hash值(後綴)命名的文件,代碼更改,生成新文件,且都會自動更新HTML中的引用(核心訴求),就像下圖:



  2. 合併雪碧圖

  3. 壓縮混淆文件

  4. 文件合併(包括JS文件和CSS文件)

能作到這幾點基本就知足了咱們的需求。前期的一切都是未知的,不太明白會遇到什麼大問題。乍看起來很是好用,若是簡單的頁面,確實會很簡單,只要簡單幾行配置就能夠搞定,但到如今FIS的配置文件200+行。一些特性很難知足,須要二次開發。上手簡單,要深刻難,必需要看源碼改源碼,寫插件,這大概就是用FIS的心得。

前期想了要怎樣把開發——測試——預發佈——發佈這個流程依賴工具流暢的跑起來,大概構思以下:

注:

  1. 調試、發佈代碼與源代碼分離

  2. 本地調試用代理如fiddler,或者上開發機

  3. deploy是構建工具同步文件的一個功能

  4. 保證源碼的版本最新,發佈代碼走ARS。

工程化進展卻不是想象中的順利,實踐中遇到了一些問題,也只能硬着頭皮咬着牙去解決。

3.2 煎熬期

  • 衝突問題
    衝突問題一直存在,在2.0時代不那麼明顯罷了。緣由是測試環境的JS已經被合併過一次。

  • 時間問題
    因爲剛開始文件比較少,構建速度基本沒啥問題。後來業務愈來愈多,參與的開發也越來約多。文件暴增到4000+,構建時間一步步增長。
    開發調試耗時 3987ms

  •  




  • 發佈構建的時候由於要進行md5計算,文件壓縮等,要181745ms!已經沒法忍了。

  • ARS流程
    用過ARS的同窗確定明白,流程仍是比較蛋疼,要完成提交SVN,點擊同步等等一系列操做,繁瑣。

  • 構建命令
    命令比較長,參數多,難以記憶

  • 產出文件多,發佈麻煩
    每改動一個字母,發佈的時候就會生成一個新的文件,發佈的時候真是在文件堆裏找!!

這一系列的問題如山倒,組內的開發同窗已經無法愉快的開發了。

3.3 深度優化

  • 減小衝突問題
    進一步解決的方案仍是細分模塊,測試環境不進行文件合併,這樣衝突的機率幾乎很小,由於公共庫通過2.0的調整已經基本穩定。

  • 縮短期
    構建時間這麼長,這樣發展下去是不行的。花了一些時間研究FIS源碼,發現FIS監聽的是整個項目文件,每一次構建都要掃描所有文件,這樣時間必然會隨着文件增長而變長。而後進行深度改造,變得不那麼像FIS了。
    進行一次又一次優化,改變構建策略。依賴構建:當某個文件依賴另外一個文件時,另外一個文件纔會被構建。假如a.html依賴了b.js ,在構建產出的文件就只有這兩個文件,其餘文件不會被構建,文件數也減小,時間大大縮短。

開發構建 (單位ms )

發佈構建 (單位ms)

  •  

  • 構建命令優化
    輸入命令麻煩,就用GUI界面,點點按鈕就行。這裏要感謝@koppthe@kolawang同窗短期內用node寫的GUI。



  • 產出文件多
    依賴構建以後,只會產出相關文件,產出文件大大減小,發佈難度減小不少。

  • ARS流程
    修復bug的時候不用ARS同步,監聽文件變化直接同步到測試環境。

  •  




  • 只須要8ms!!!。若是打開了同步按鈕,修改的文件會立立刻傳到測試環境上,會不會有相互覆蓋的問題。組內每一個人負責的模塊都不一樣,並且公共模塊已經基本穩定,很難出現這樣的問題,在實踐中不多發生這樣的事情,相反小夥伴以爲簡直得到解脫,相比找文件傳文件這樣繁瑣的流程,這輕鬆了許多。

  • 發佈優化
    構建工具會產出文件列表,點擊就能打開文件夾,找到對應文件;列表對應SVN路徑,直接貼到ARS就能提單。

  • 雪碧圖的優化
    發佈的時候全部引用的CSS文件會合併成一個,而後將引用的圖標合併爲雪碧圖,有點粗暴。由於公共的CSS文件的圖片單獨合併爲雪碧圖會更加合理,公共的圖片變更頻率不會那麼高。開發一插件,在CSS合併前雪碧圖一次,合併後再雪碧圖一次。

統計與優化

用戶網絡類型(粗略)

unknown是沒法統計到的,理論上wifi仍是佔大部分。從其餘四種類型看,wifi佔據絕大部分,2g用戶很是少。

PC VS Mobile


在JS下載和執行效率上,移動端明顯要低於PC端。

JS優化

以前APP內部的JS文件都是經過seajs來下載文件,後來發覺何不直接乾脆點直接寫<script>下載就行了,優化後下載執行時間降低顯著:

 


注:這裏統計的時間,包括了下載JS和執行JS的時間。

JS內嵌與外聯對比

在考慮優化的時候,咱們一種方案即是將外聯的JS代碼(僅業務代碼)經過工具內嵌到頁面。如今來對比下性能:
http://gqq.gtimg.com/static/mobile/js/v3/page/gift/list/inappand.a9a524eb.lc.js 文件大小8.7kb,gzip壓縮後3.3kb。
內聯加載時間幾乎爲0 0.0015793,外聯的下載時間:

 


下載時間不到200ms,但相對來講已是很長了,才8.7kb。

咱們知道,DOMContentLoaded事件的觸發基本意味着頁面已經渲染完成,JS已經執行(異步的除外),已經達到可交互的狀態了,具體可參考這篇文章。下面看下內聯與外聯對DOMContentLoaded的影響:

藍色線條是外聯的JS,時間明顯要比內聯的高出一些,大概200ms。因而可知,將小量的JS文件內聯到頁面,可以提升速度。但大的JS文件適不適合內聯,目前尚未實驗。這裏須要在減小HTTP請求和利用緩存之間把握一個平衡,不少時候優化準則是並非那麼容易實施,由於可能自相矛盾,也可能和工程自己相矛盾。優化不是按照準則照本宣科的作,須要靈活變通。

優化措施
按照雅虎優化的14條準則,把還沒作到的都處理了。

  • 腳本域名切換,去cookie。

  • 文件合併

  • 利用瀏覽器緩存,無限增大緩存期max-age=15552000

  • 雪碧圖

  • 減小HTTP請求,構建工具內嵌JS到HTML

感受速度仍是不夠快,再充分利用本地緩存和APP提供的緩存能力

  • 瀏覽器使用localstorage緩存腳本

  • APP緩存hash文件名腳本

  • 緩存HTML片斷

調試、測試、體驗流程

反向代理+白名單控制策略,域名對外訪問是403,公司內網可訪問。不用代理,手機直接鏈接wifi訪問。環境分爲開發——測試——預發佈——正式(每一個環境對應一個獨立域名),任何角色(開發、測試、設計、產品)均可隨時訪問。

APP的debug包,可任意切換上面四種環境進行調試、測試、體驗。

總結

這是過去一年工做的總結,一直都沒靜下來梳理。回過頭想,本身是否是把這個流程變得更加複雜了。可能都有一個從簡單到複雜再到簡單的過程,堅持優化一直沒有停下來,只要可以變得更好一點點,都會去嘗試,所謂生命不息,折騰不止。

做者:addy(許斌)

相關文章
相關標籤/搜索