第一篇:一些前端開發(fā)優(yōu)化的經(jīng)驗(yàn)總結(jié)
一些前端開發(fā)優(yōu)化的經(jīng)驗(yàn)總結(jié)
發(fā)現(xiàn)的一篇關(guān)于前端優(yōu)化的文章,總結(jié)的很全面,要做到面面俱到很難,往往是想優(yōu)化而沒有時(shí)間去優(yōu)化,就像我們公司,一個(gè)項(xiàng)目連著一個(gè)項(xiàng)目~新員工的培訓(xùn)都省了,還想優(yōu)化前端啊,不過我真的想有機(jī)會(huì)和老大好好的整合下公司網(wǎng)站的前端代碼~不過要把前端優(yōu)化的工作放在平時(shí)的寫代碼中去,就不需要刻意的后期優(yōu)化了。在項(xiàng)目開發(fā)中,后臺(tái)需要搭建好框架,前端更是需要搭建好框架,并且在頁面實(shí)現(xiàn)中得到實(shí)現(xiàn),只有這樣才能事半功倍。
前段時(shí)間簡單的研究了下前端優(yōu)化相關(guān)的知識(shí),本文算是一個(gè)階段性的總結(jié),或者當(dāng)做一個(gè)優(yōu)化的參考List。
前言
前端是龐大的,包括HTML、CSS、Javascript、Image、Flash等等各種各樣的資源。前端優(yōu)化是復(fù)雜的,針對(duì)方方面面的資源都有不同的方式。那么,前端優(yōu)化的目的是什么?
1.從用戶角度而言,優(yōu)化能夠讓頁面加載得更快、對(duì)用戶的操作響應(yīng)得更及時(shí),能夠給用戶提供更為友好的體驗(yàn)。
2.從服務(wù)商角度而言,優(yōu)化能夠減少頁面請(qǐng)求數(shù)、或者減小請(qǐng)求所占帶寬,能夠節(jié)省可觀的資源??傊?,恰當(dāng)?shù)膬?yōu)化不僅能夠改善站點(diǎn)的用戶體驗(yàn)并且能夠節(jié)省相當(dāng)?shù)馁Y源利用。前端優(yōu)化的途徑有很多,按粒度大致可以分為兩類,第一類是頁面級(jí)別的優(yōu)化,例如HTTP請(qǐng)求數(shù)、腳本的無阻塞加載、內(nèi)聯(lián)腳本的位置優(yōu)化等;第二類則是代碼級(jí)別的優(yōu)化,例如Javascript中的DOM操作優(yōu)化、CSS選擇符優(yōu)化、圖片優(yōu)化以及HTML結(jié)構(gòu)優(yōu)化等等。另外,本著提高投入產(chǎn)出比的目的,后文提到的各種優(yōu)化策略大致按照投入產(chǎn)出比從大到小的順序排列。
一、頁面級(jí)優(yōu)化
1.減少HTTP請(qǐng)求數(shù)
這條策略基本上所有前端人都知道,而且也是最重要最有效的。都說要減少HTTP請(qǐng)求,那請(qǐng)求多了到底會(huì)怎么樣呢?首先,每個(gè)請(qǐng)求都是有成本的,既包含時(shí)間成本也包含資源成本。一個(gè)完整的請(qǐng)求都需要經(jīng)過DNS尋址、與服務(wù)器建立連接、發(fā)送數(shù)據(jù)、等待服務(wù)器響應(yīng)、接收數(shù)據(jù)這樣一個(gè)“漫長”而復(fù)雜的過程。時(shí)間成本就是用戶需要看到或者“感受”到這個(gè)資源是必須要等待這個(gè)過程結(jié)束的,資源上由于每個(gè)請(qǐng)求都需要攜帶數(shù)據(jù),因此每個(gè)請(qǐng)求都需要占用帶寬。另外,由于瀏覽器進(jìn)行并發(fā)請(qǐng)求的請(qǐng)求數(shù)是有上限的(具體參見此處),因此請(qǐng)求數(shù)多了以后,瀏覽器需要分批進(jìn)行請(qǐng)求,因此會(huì)增加用戶的等待時(shí)間,會(huì)給用戶造成站點(diǎn)速度慢這樣一個(gè)印象,即使可能用戶能看到的第一屏的資源都已經(jīng)請(qǐng)求完了,但是瀏覽器的進(jìn)度條會(huì)一直存在。減少HTTP請(qǐng)求數(shù)的主要途徑包括:(1).從設(shè)計(jì)實(shí)現(xiàn)層面簡化頁面
如果你的頁面像百度首頁一樣簡單,那么接下來的規(guī)則基本上都用不著了。保持頁面簡潔、減少資源的使用時(shí)最直接的。如果不是這樣,你的頁面需要華麗的皮膚,則繼續(xù)閱讀下面的內(nèi)容。(2).合理設(shè)置HTTP緩存
緩存的力量是強(qiáng)大的,恰當(dāng)?shù)木彺嬖O(shè)置可以大大的減少HTTP請(qǐng)求。以有啊首頁為例,當(dāng)瀏覽器沒有緩存的時(shí)候訪問一共會(huì)發(fā)出78個(gè)請(qǐng)求,共600多K數(shù)據(jù)(如圖1.1),而當(dāng)?shù)诙卧L問即瀏覽器已緩存之后訪問則僅有10個(gè)請(qǐng)求,共20多K數(shù)據(jù)(如圖1.2)。(這里需要說明的是,如果直接F5刷新頁面的話效果是不一樣的,這種情況下請(qǐng)求數(shù)還是一樣,不過被緩存資源的請(qǐng)求服務(wù)器是304響應(yīng),只有Header沒有Body,可以節(jié)省帶寬)
如圖1.1
如圖1.2 怎樣才算合理設(shè)置?原則很簡單,能緩存越多越好,能緩存越久越好。例如,很少變化的圖片資源可以直接通過HTTP Header中的Expires設(shè)置一個(gè)很長的過期頭;變化不頻繁而又可能會(huì)變的資源可以使用Last-Modifed來做請(qǐng)求驗(yàn)證。盡可能的讓資源能夠在緩存中待得更久。關(guān)于HTTP緩存的具體設(shè)置和原理此處就不再詳述了,有興趣的可以參考下列文章: HTTP1.1協(xié)議中關(guān)于緩存策略的描述
Fiddler HTTP Performance中關(guān)于緩存的介紹(3).資源合并與壓縮
如果可以的話,盡可能的將外部的腳本、樣式進(jìn)行合并,多個(gè)合為一個(gè)。另外,CSS、Javascript、Image都可以用相應(yīng)的工具進(jìn)行壓縮,壓縮后往往能省下不少空間。
(4).CSS Sprites 合并CSS圖片,減少請(qǐng)求數(shù)的又一個(gè)好辦法。(5).Inline Images 使用data: URL scheme的方式將圖片嵌入到頁面或CSS中,如果不考慮資源管理上的問題的話,不失為一個(gè)好辦法。如果是嵌入頁面的話換來的是增大了頁面的體積,而且無法利用瀏覽器緩存。使用在CSS中的圖片則更為理想一些。(6).Lazy Load Images 這條策略實(shí)際上并不一定能減少HTTP請(qǐng)求數(shù),但是卻能在某些條件下或者頁面剛加載時(shí)減少HTTP請(qǐng)求數(shù)。對(duì)于圖片而言,在頁面剛加載的時(shí)候可以只加載第一屏,當(dāng)用戶繼續(xù)往后滾屏的時(shí)候才加載后續(xù)的圖片。這樣一來,假如用戶只對(duì)第一屏的內(nèi)容感興趣時(shí),那剩余的圖片請(qǐng)求就都節(jié)省了。有啊首頁曾經(jīng)的做法是在加載的時(shí)候把第一屏之后的圖片地址緩存在Textarea標(biāo)簽中,待用戶往下滾屏的時(shí)候才“惰性”加載。2.將外部腳本置底
前文有談到,瀏覽器是可以并發(fā)請(qǐng)求的,這一特點(diǎn)使得其能夠更快的加載資源,然而外鏈腳本在加載時(shí)卻會(huì)阻塞其他資源,例如在腳本加載完成之前,它后面的圖片、樣式以及其他腳本都處于阻塞狀態(tài),直到腳本加載完成后才會(huì)開始加載。如果將腳本放在比較靠前的位置,則會(huì)影響整個(gè)頁面的加載速度從而影響用戶體驗(yàn)。解決這一問題的方法有很多,在這里有比較詳細(xì)的介紹(這里是譯文和更詳細(xì)的例子),而最簡單可依賴的方法就是將腳本盡可能的往后挪,減少對(duì)并發(fā)下載的影響。
3.異步執(zhí)行inline腳本
inline腳本對(duì)性能的影響與外部腳本相比,是有過之而無不及。首頁,與外部腳本一樣,inline腳本在執(zhí)行的時(shí)候一樣會(huì)阻塞并發(fā)請(qǐng)求,除此之外,由于瀏覽器在頁面處理方面是單線程的,當(dāng)inline腳本在頁面渲染之前執(zhí)行時(shí),頁面的渲染工作則會(huì)被推遲。簡而言之,inline腳本在執(zhí)行的時(shí)候,頁面處于空白狀態(tài)。鑒于以上兩點(diǎn)原因,建議將執(zhí)行時(shí)間較長的inline腳本異步執(zhí)行,異步的方式有很多種,例如使用script元素的defer屬性(存在兼容性問題和其他一些問題,例如不能使用document.write)、使用setTimeout,此外,在HTML5中引入了Web Workers的機(jī)制,恰恰可以解決此類問題。4.Lazy Load Javascript
隨著Javascript框架的流行,越來越多的站點(diǎn)也使用起了框架。不過,一個(gè)框架往往包括了很多的功能實(shí)現(xiàn),這些功能并不是每一個(gè)頁面都需要的,如果下載了不需要的腳本則算得上是一種資源浪費(fèi)-既浪費(fèi)了帶寬又浪費(fèi)了執(zhí)行花費(fèi)的時(shí)間。目前的做法大概有兩種,一種是為那些流量特別大的頁面專門定制一個(gè)專用的mini版框架,另一種則是Lazy Load。YUI則使用了第二種方式,在YUI的實(shí)現(xiàn)中,最初只加載核心模塊,其他模塊可以等到需要使用的時(shí)候才加載。5.將CSS放在HEAD中
如果將CSS放在其他地方比如BODY中,則瀏覽器有可能還未下載和解析到CSS就已經(jīng)開始渲染頁面了,這就導(dǎo)致頁面由無CSS狀態(tài)跳轉(zhuǎn)到CSS狀態(tài),用戶體驗(yàn)比較糟糕。除此之外,有些瀏覽器會(huì)在CSS下載完成后才開始渲染頁面,如果CSS放在靠下的位置則會(huì)導(dǎo)致瀏覽器將渲染時(shí)間推遲。6.異步請(qǐng)求Callback
在某些頁面中可能存在這樣一種需求,需要使用script標(biāo)簽來異步的請(qǐng)求數(shù)據(jù)。類似:
以下是代碼片段: Javascript: function myCallback(info){ //do something here } HTML 以下是代碼片段:
callback返回的內(nèi)容: myCallback('Hello world!');
像以上這種方式直接在頁面上寫