前端優(yōu)化帶來的思考,淺談前端工程化

重復(fù)優(yōu)化的思考

當(dāng)然,由于js加載是順序是不可控的,我們需要為seed.js實(shí)現(xiàn)一個(gè)最簡單的順序加載模塊,映射什么的由構(gòu)建工具完成,每次做覆蓋發(fā)布即可,這樣做的缺點(diǎn)是額外增加一個(gè)seed.js的文件,并且要承擔(dān)模塊加載代碼的下載量。

localstorage緩存

也會(huì)有團(tuán)隊(duì)將靜態(tài)資源緩存至localstorage中,以期做離線應(yīng)用,但是我一般用它存json數(shù)據(jù),沒有做過靜態(tài)資源的存儲(chǔ),想要嘗試的朋友一定要做好資源更新的策略,然后localstorage的讀寫也有一定損耗,不支持的情況還需要做降級(jí)處理,這里便不多介紹。

Hybrid載入

如果是Hybrid的話,情況有所不同,需要將公共資源打包至native中,業(yè)務(wù)類就不要打包了,否則native會(huì)越來越大。

服務(wù)器資源合并

之前與淘寶的一些朋友做過交流,發(fā)現(xiàn)他們居然做到了零散資源在服務(wù)器端做合并的地步了……這方面我們還是望洋興嘆吧

工程化&前端優(yōu)化

所謂工程化,可以簡單認(rèn)為是將框架的職責(zé)拓寬再拓寬,主旨是幫業(yè)務(wù)團(tuán)隊(duì)更好的完成需求,工程化會(huì)預(yù)測一些常碰到的問題,將之扼殺在搖籃,而這種路徑是可重用的,是具有可持續(xù)性的,比如第一個(gè)優(yōu)化去除冗余,是在多次去除冗余代碼,思考冗余出現(xiàn)的原因而最終思考得出的一個(gè)避免冗余的方案,前端工程化需要考慮以下問題:

重復(fù)工作;如通用的流程控制機(jī)制,可擴(kuò)展的UI組件、靈活的工具方法

重復(fù)優(yōu)化;如降低框架層面升級(jí)帶給業(yè)務(wù)團(tuán)隊(duì)的耗損、幫助業(yè)務(wù)在無感知情況下做掉大部分優(yōu)化(比如打包壓縮什么的)

開發(fā)效率;如幫助業(yè)務(wù)團(tuán)隊(duì)寫可維護(hù)的代碼、讓業(yè)務(wù)團(tuán)隊(duì)方便的調(diào)試代碼(比如Hybrid調(diào)試)

構(gòu)建工具

要完成前端工程化,少不了工程化工具,requireJS與grunt的出現(xiàn),改變了業(yè)界前端代碼的編寫習(xí)慣,同時(shí)他們也是推動(dòng)前端工程化的一個(gè)基礎(chǔ)。

requireJS是一偉大的模塊加載器,他的出現(xiàn)讓javascript制作多人維護(hù)的大型項(xiàng)目變成了事實(shí);grunt是一款javascript構(gòu)建工具,主要完成壓縮、合并、圖片壓縮合并等一系列工作,后續(xù)又出了yeoman、Gulp、webpack等構(gòu)建工具。

這里這里要記住一件事情,我們的目的是完成前端工程化,無論什么模塊加載器或者構(gòu)建工具,都是為了幫助我們完成目的,工具不重要,目的與思想才重要,所以在完成工程化前討論哪個(gè)加載器好,哪種構(gòu)建工具好是舍本逐末的。

理想的載入速度

現(xiàn)在站在前端優(yōu)化的角度,以下面這個(gè)頁面為例,最優(yōu)的載入情況是什么呢:

以這個(gè)看似簡單頁面來說,如果要完整的展示涉及的模塊比較多:

① 框架MVC骨架模塊&框架級(jí)別CSS

② 幾個(gè)UI組件(header組件、日歷、彈出層、消息框……)

③ 業(yè)務(wù)HTML骨架

④ 業(yè)務(wù)CSS

⑤ 業(yè)務(wù)Javascript代碼

⑥ 服務(wù)接口服務(wù)

上面的很多資源事實(shí)上對(duì)于首屏渲染是沒有幫助的,根據(jù)之前的探討,得出的理想首屏加載所需資源是:

① 框架MVC骨架&框架級(jí)別CSS => main.css+libs.js

② 業(yè)務(wù)入口文件 => main.js

③ 業(yè)務(wù)交互控制器 => page.js

有了這些資源,便能完成完整的交互,包括接口請(qǐng)求,列表展示,但若是只需要給用戶“看見”首頁,便能采用一種fake的手段,只需要這些資源:

① 業(yè)務(wù)HTML骨架 => 最簡單的index.hrml載入

② 內(nèi)嵌CSS

這個(gè)時(shí)候,頁面一旦下載結(jié)束便可完成渲染,在其它資源加載結(jié)束后再將頁面重新渲染即可,很多時(shí)候前端優(yōu)化要做的就是靠近這種理想載入速度,解決那些制約的因素,比如:

CSS Sprite

由于現(xiàn)代瀏覽器的與解析機(jī)制,在拿到一個(gè)頁面的時(shí)候馬上會(huì)分析其靜態(tài)資源,然后開線程做下載,這個(gè)時(shí)候反而會(huì)影響首屏渲染,如圖(模擬2G):

如果做fake頁優(yōu)化的話,便需要將樣式也做異步載入,這樣document載入結(jié)束便能渲染頁面,2G情況都能3S內(nèi)可見頁面,大大避免白屏?xí)r間,而后面的單個(gè)背景圖片便是需要解決的工程問題。

CSS Sprite旨在降低請(qǐng)求數(shù),但是與去處冗余問題一樣,半年后一個(gè)CSS Sprite資源反而不好維護(hù),容易爛掉,grunt有一插件支持將圖片自動(dòng)合并為CSS Sprite,而他也會(huì)自動(dòng)替換頁面中的背景地址,只需要按規(guī)則操作即可。

PS:其它構(gòu)建工具也會(huì)有,各位自己找下吧

CSS Sprite構(gòu)建工具:https://www.npmjs.com/package/grunt-css-sprite

正確的使用該工具便可以使業(yè)務(wù)開發(fā)擺脫圖片合并帶來的痛苦,當(dāng)然一些弊端需要去克服,比如在小屏手機(jī)使用小屏背景,大屏手機(jī)使用大屏背景的處理辦法

其它工程化的體現(xiàn)

又比如,前端模板是將html文件解析為function函數(shù),這一步驟完全可以在發(fā)布階段,將html模板轉(zhuǎn)換為function函數(shù),免去了生產(chǎn)環(huán)境的大量正則替換,效率高還省電;

然后ajax接口數(shù)據(jù)的緩存也直接在數(shù)據(jù)請(qǐng)求底層做掉,讓業(yè)務(wù)輕松實(shí)現(xiàn)接口數(shù)據(jù)緩存;

而一些html壓縮、預(yù)加載技術(shù)、延遲加載技術(shù)等優(yōu)化點(diǎn)便不一一展開……

渲染優(yōu)化

當(dāng)請(qǐng)求資源落地后便是瀏覽器的渲染工作了,每一次操作皆可能引起瀏覽器的重繪,在PC瀏覽器上,渲染對(duì)性能影響不大,但因?yàn)榕渲迷颍秩緦?duì)移動(dòng)端性能的影響卻非常大,錯(cuò)誤的操作可能導(dǎo)致滾動(dòng)遲鈍、動(dòng)畫卡幀,大大降低用戶體驗(yàn)。

減少重繪、減少回流降低渲染帶來的耗損基本人盡皆知了,但是引起重繪的操作何其多,每次重繪的操作又何其微觀:

① 頁面滾動(dòng)

② javascript交互

③ 動(dòng)畫

④ 內(nèi)容變化

⑤ 屬性計(jì)算(求元素的高寬)

……

與請(qǐng)求優(yōu)化不同的是,一些請(qǐng)求是可以避免的,但是重繪基本是不可避免的,而如果一個(gè)頁面卡了,這么多可能引起重繪的操作,如何定位到渲染瓶頸在何處,如何減少這種大消耗的性能影響是真正應(yīng)該關(guān)心的問題。

Chrome渲染分析工具

工程化其中要解決的一個(gè)問題是代碼調(diào)試問題,以前端開發(fā)來說Chrome以及Fiddler在這方面已經(jīng)做的非常好了,這里就使用Chrome來查看一下頁面的渲染。

Timeline工具

timeline可以展示web應(yīng)用加載過程中的資源消耗情況,包括處理DOM事件,頁面布局渲染以及繪制元素,通過該工具基本可以找到頁面存在的渲染問題。

Timeline使用4種顏色表示不同的事件:

藍(lán)色:加載耗時(shí)

黃色:腳本執(zhí)行耗時(shí)

紫色:渲染耗時(shí)

綠色:繪制耗時(shí)

以上圖為例,因?yàn)樗⑿铝隧撁妫瑫?huì)加載幾個(gè)完整的js文件,所以js執(zhí)行耗時(shí)必然會(huì)多,但也在50ms左右就結(jié)束了。

Rendering工具

Chrome還有一款工具為分析渲染而生:

1 Show paint rectangles 顯示繪制矩形

2 Show composited layer borders 顯示層的組合邊界

3 Show FPS meter 顯示FPS幀頻

4 Enable continuous page repainting 開啟持續(xù)繪制模式 并 檢測頁面繪制時(shí)間

5 Show potential scroll bottlenecks 顯示潛在的滾動(dòng)瓶頸。

show paint rectangles

開啟矩形框,便會(huì)有綠色的框?qū)㈨撁嬷胁煌脑乜蚱饋恚绻撁驿秩颈銜?huì)整塊加深,舉個(gè)例子:

當(dāng)點(diǎn)擊+號(hào)時(shí),三塊區(qū)域產(chǎn)生了重繪,這里也可以看出,每次重繪都會(huì)影響一個(gè)塊級(jí)(Layer),連帶反應(yīng)會(huì)影響周邊元素,所以一次mask全局遮蓋層的出現(xiàn)會(huì)導(dǎo)致頁面級(jí)重繪,比如這里的loading與toast便有所不同:

loading由于遮蓋mask的出現(xiàn)而產(chǎn)生了全局重繪,而toast本身是絕對(duì)定位元素只影響了局部,這里有一個(gè)需要注意的是,因?yàn)閘oading轉(zhuǎn)圈的動(dòng)畫是CSS3實(shí)現(xiàn)的,雖然不停的再動(dòng),事實(shí)上只渲染了一次,如果采用javascript的話,便會(huì)不停重繪。

然后當(dāng)頁面發(fā)生滾動(dòng)時(shí),下面的支付工具條一直呈綠色狀態(tài),意思是滾動(dòng)時(shí)一直在重繪,這個(gè)重繪的頻率很高,這也是fixed元素相當(dāng)耗費(fèi)性能的原因:

結(jié)合Timeline的渲染圖

如果這里取消掉fixed元素的話:

這里fixed元素支付工具欄滾動(dòng)時(shí)候是綠的,但是同樣是fixed的header卻沒有變綠,那是因?yàn)閔eader多了一個(gè)css屬性:

.cm-header {

-webkit-transform: translate3d(0,0,0);

transform: translate3d(0,0,0);

}

這個(gè)屬性會(huì)創(chuàng)建獨(dú)立的Layer,有效的降低了fixed屬性的性能損耗,如果header去掉此屬性的話,就不一樣了:

show composited layer borders

顯示組合層邊界,是因?yàn)轫撁媸怯啥鄠€(gè)圖層組成,勾上后頁面便開始分塊了:

使用該工具可以查看當(dāng)前頁面Layer構(gòu)成,這里的+號(hào)以及header都是有自己獨(dú)立的圖層的,原因是使用了:

transform: translate3d(-50%,-50%,0);

Layer存在的意義在于可以讓頁面最優(yōu)的方式繪制,這個(gè)是CSS3硬件加速的秘密,就如header一樣,形成Layer的元素繪制會(huì)有所不同。

Layer的創(chuàng)建會(huì)消耗額外的資源,所以不能不加節(jié)制的使用,以上面的“+”來說,如果使用icon font效果也許更好。

因?yàn)殇秩具@個(gè)東西比較底層,需要對(duì)瀏覽器層面的了解更多,關(guān)于更多更全的渲染相關(guān)知識(shí),推薦閱讀我好友的博客:

http://www.ghugo.com/

結(jié)語

今天我們站在工程化的層面總結(jié)了前幾次性能優(yōu)化的一些方法,以期在后續(xù)的項(xiàng)目開發(fā)中能直接繞過這些性能的問題。

前端優(yōu)化僅僅是前端工程化中的一環(huán),結(jié)合之前的代碼開發(fā)效率探討(【組件化開發(fā)】前端進(jìn)階篇之如何編寫可維護(hù)可升級(jí)的代碼),后續(xù)我們會(huì)在前端工具的制作使用、前端監(jiān)控等環(huán)節(jié)做更多的工作,期望更大的提升前端開發(fā)的效率,推動(dòng)前端工程化的進(jìn)程。

本文關(guān)聯(lián)的代碼:https://github.com/yexiaochai/mvc

原文:http://www.codeceo.com/article/front-improvement.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,818評(píng)論 25 708
  • 性能優(yōu)化方向分類 請(qǐng)求數(shù)量: 合并腳本和樣式表, CSS Sprites, 拆分初始化負(fù)載, 劃分主域(使用“查找...
    Www劉閱讀 1,787評(píng)論 3 8
  • 前言 前端的工作并不僅僅是實(shí)現(xiàn)「視覺&交互稿」,想要開發(fā)一個(gè)高性能易維護(hù)的「完美」站點(diǎn)并未易事,針對(duì)前端的性能優(yōu)化...
    木羽zwwill閱讀 651評(píng)論 0 4
  • 走吧,讓我們一起回到起點(diǎn) 攜手來到故事的開場 自私而又輕狂 任憑風(fēng)聲消失在海里 安排一次嶄新的日出 就我和你,等待...
    柳小七閱讀 268評(píng)論 0 0