前端優化手段

前端優化,其實就幾句話: javascript

傳輸層面:減小請求數,下降請求量
執行層面:減小重繪&迴流

傳輸層面的歷來都是優化的核心點,而這個層面的優化要對瀏覽器有一個基本的認識,好比:css

① 網頁自上而下的解析渲染,邊解析邊渲染,頁面內CSS文件會阻塞渲染,異步CSS文件會致使迴流html

② 瀏覽器在document下載結束會檢測靜態資源,新開線程下載(有併發上限),在帶寬限制的條件下,無序併發會致使主資源速度降低,從而影響首屏渲染前端

③ 瀏覽器緩存可用時會使用緩存資源,這個時候能夠避免請求體的傳輸,對性能有極大提升java

 

衡量性能的重要指標爲首屏載入速度(指頁面能夠看見,不必定可交互),影響首屏的最大因素爲請求,因此請求是頁面真正的殺手,通常來講咱們會作這些優化:webpack

 

減小請求數

 

① 合併樣式、腳本文件web

 

② 合併背景圖片json

 

③ CSS3圖標、Icon Font前端工程化

 

下降請求量

 

① 開啓GZip瀏覽器

 

② 優化靜態資源,jQuery->Zepto、閹割IScroll、去除冗餘代碼

 

③ 圖片無損壓縮

 

④ 圖片延遲加載

 

⑤ 減小Cookie攜帶

 

不少時候,咱們也會採用相似「時間換空間、空間換時間」的作法,好比:

 

① 緩存爲王,對更新較緩慢的資源&接口作緩存(瀏覽器緩存、localsorage、application cache這個坑多)

 

② 按需加載,先加載主要資源,其他資源延遲加載,對非首屏資源滾動加載

 

③ fake頁技術,將頁面最初須要顯示Html&Css內聯,在頁面所需資源加載結束前至少可看,理想狀況是index.html下載結束即展現(2G 5S內)

 

④ CDN

 

從工程的角度來看,上述優化點半數以上是重複的,通常在發佈時候就直接使用項目構建工具作掉了,還有一些只是簡單的服務器配置,開發時不須要關注。

能夠看到,咱們所作的優化都是在減小請求數,下降請求量,減少傳輸時的耗時,或者經過一個策略,優先加載首屏渲染所需資源,然後再加載交互所需資源(好比點擊時候再加載UI組件),Hybrid APP這方面應該儘量多的將公共靜態資源放在native中,好比第三方庫,框架,UI甚至城市列表這種經常使用業務數據。

 

攔路虎

 

有一些網站初期比較快,可是隨着量的積累,BUG愈來愈多,速度也愈來愈慢,一些前端會使用上述優化手段作優化,可是收效甚微,一個比較典型的例子就是代碼冗餘:

 

① 以前的CSS所有放在了一個文件中,新一輪的UI樣式優化,新老CSS難以拆分,CSS體量會增長,若是有業務團隊使用了公共樣式,狀況更不容樂觀;

 

② UI組件更新,可是若是有業務團隊脫離接口操做了組件DOM,將致使新組件DOM更新受限,最差的狀況下,用戶會加載兩個組件的代碼;

 

③ 胡亂使用第三方庫、組件,致使頁面加載大量無用代碼;

 

......

 

以上問題會不一樣程度的增長資源下載體量,若是聽之任之會產生一系列工程問題:

 

① 頁面關係錯綜複雜,需求迭代容易出BUG;

 

② 框架每次升級都會致使額外的請求量,常加載一些業務不須要的代碼;

 

③ 第三方庫氾濫,且難以維護,有BUG也改不了;

 

④ 業務代碼加載大量異步模塊資源,頁面請求數增多;

 

......

 

爲求快速佔領市場,業務開發時間每每緊迫,使用框架級的HTML&CSS、繞過CSS Sprite使用背景圖片、引入第三方工具庫或者UI,會常常發生。當遇到性能瓶頸時,若是不從根源解決問題,用傳統的優化手段作頁面級別的優化,會出現很快頁面又被玩壞的狀況,幾回優化結束後我也在思考一個問題:

 
前端每次性能優化的手段皆大同小異;代碼的可維護性也基本是在細分職責;
既然每次優化的目的是相同的,每次實現的過程是類似的,而每次從新開發項目又基本是要重蹈覆轍的,那麼工程化、自動化多是這一切問題的最終答案
 

工程問題在項目積累到必定量後可能會發生,通常來講會有幾個現象預示着工程問題出現了:

 

① 代碼編寫&調試困難

 

② 業務代碼很差維護

 

③ 網站性能廣泛很差

 

④ 性能問題重複出現,而且有不可修復之勢

 

像上面所描述狀況,就是一個典型的工程問題;定位問題、發現問題、解決問題是咱們處理問題的手段;而如何防止同一類型的問題重複發生,即是工程化須要作的事情,簡單說來,優化是解決問題,工程化是避免問題,今天咱們就站在工程化的角度來解決一些前端優化問題,防止其死灰復燃。

 

資源加載

解決冗餘便拋開了歷史的包袱,是前端優化的第一步也是比較難的一步,但模塊拆分也將全站分紅了不少小的模塊,載入的資源分散會增長請求數;若是所有合併,會致使首屏加載不須要的資源,也會致使下一個頁面不能使用緩存,如何作出合理的入口資源加載規則,如何合理的善用緩存,是前端優化的第二步。

通過幾回性能優化對比,得出了一個較優的首屏資源加載方案:

① 核心框架層:mvc骨架、異步模塊加載器(require&seajs)、工具庫(zepto、underscore、延遲加載)、數據請求模塊、核心依賴UI(header組件消息類組件)

② 業務公共模塊:入口文件(require配置,初始化工做、業務公共模塊)

③ 獨立的page.js資源(包含template、css),會按需加載獨立UI資源

④ 全局css資源

這裏若是追求極致,libs.js、main.css與main.js能夠選擇合併,劃分結束後即可以決定靜態資源緩存策略了。

 

資源緩存

資源緩存是爲二次請求加速,比較經常使用的緩存技術有:

① 瀏覽器緩存

② localstorage緩存

③ application緩存

application緩存更新一塊很差把握容易出問題,因此更多的是依賴瀏覽器以及localstorage,首先說下瀏覽器級別的緩存。

 

時間戳更新

只要服務器配置,瀏覽器自己便具備緩存機制,若是要使用瀏覽器機制做緩存,勢必關心一個什麼時候更新資源問題,咱們通常是這樣作的:

<script type="text/javascript" src="libs.js?t=20151025"></script>

 

這樣作要求必須先發布js文件,才能發佈html文件,不然讀不到最新靜態文件的。

一個比較尷尬的場景是libs.js是框架團隊甚至第三方公司維護的,和業務團隊的index.html是兩個團隊,互相的發佈是沒有關聯的,因此這二者的發佈順序是不能保證的,因而轉向開始使用了MD5的方式。

 

MD5時代

爲了解決以上問題咱們開始使用md5碼的方式爲靜態資源命名:

<script type="text/javascript" src="libs_md5_1234.js"></script>

 

每次框架更新便不作文件覆蓋,直接生成一個惟一的文件名作增量發佈,這個時候若是框架先發布,待業務發佈時便已經存在了最新的代碼;當業務先發布框架沒有新的時,便繼續沿用老的文件,一切都很美好,雖然業務開發偶爾會抱怨每次都要向框架拿MD5映射,直到框架一次BUG發生。

 

seed.js時代

忽然一天框架發現一個全局性BUG,而且立刻作出了修復,業務團隊也立刻發佈上線,但這種事情出現第二次、第三次框架這邊便壓力大了,這個時候框架層面但願業務只須要引用一個不帶緩存的seed.js,seed.js要怎麼加載是他本身的事情:

<script type="text/javascript" src="seed.js"></script>
//seed.js須要按需加載的資源
<script src="libs_md5.js"></script>
<script src="main_md5.js"></script>

固然,因爲js加載是順序是不可控的,咱們須要爲seed.js實現一個最簡單的順序加載模塊,映射什麼的由構建工具完成,每次作覆蓋發佈便可,這樣作的缺點是額外增長一個seed.js的文件,而且要承擔模塊加載代碼的下載量。

localstorage緩存

也會有團隊將靜態資源緩存至localstorage中,以期作離線應用,可是我通常用它存json數據,沒有作過靜態資源的存儲,想要嘗試的朋友必定要作好資源更新的策略,而後localstorage的讀寫也有必定損耗,不支持的狀況還須要作降級處理,這裏便很少介紹。

Hybrid載入

若是是Hybrid的話,狀況有所不一樣,須要將公共資源打包至native中,業務類就不要打包了,不然native會愈來愈大。

 

工程化&前端優化

所謂工程化,能夠簡單認爲是將框架的職責拓寬再拓寬,主旨是幫業務團隊更好的完成需求,工程化會預測一些常碰到的問題,將之扼殺在搖籃,而這種路徑是可重用的,是具備可持續性的,好比第一個優化去除冗餘,是在屢次去除冗餘代碼,思考冗餘出現的緣由而最終思考得出的一個避免冗餘的方案,前端工程化須要考慮如下問題:

重複工做;如通用的流程控制機制,可擴展的UI組件、靈活的工具方法
重複優化;如下降框架層面升級帶給業務團隊的耗損、幫助業務在無感知狀況下作掉大部分優化(好比打包壓縮什麼的)
開發效率;如幫助業務團隊寫可維護的代碼、讓業務團隊方便的調試代碼(好比Hybrid調試)

構建工具

要完成前端工程化,少不了工程化工具,requireJS與grunt的出現,改變了業界前端代碼的編寫習慣,同時他們也是推進前端工程化的一個基礎。

requireJS是一偉大的模塊加載器,他的出現讓javascript製做多人維護的大型項目變成了事實;grunt是一款javascript構建工具,主要完成壓縮、合併、圖片壓縮合並等一系列工做,後續又出了yeoman、Gulp、webpack等構建工具。

這裏這裏要記住一件事情,咱們的目的是完成前端工程化,不管什麼模塊加載器或者構建工具,都是爲了幫助咱們完成目的,工具不重要,目的與思想才重要,因此在完成工程化前討論哪一個加載器好,哪一種構建工具好是捨本逐末的。

相關文章
相關標籤/搜索