談到網(wǎng)站優(yōu)化這塊,不管是前端后端都有許多各自的優(yōu)化技巧,這個系列針對的是前端部分的優(yōu)化;
標題是JavaScript性能提升,為什么說是JavaScript的性能優(yōu)化呢,事實上如果一個網(wǎng)頁完全不使用JavaScript的話可以使用的前端優(yōu)化技巧微乎其微,正因為有JavaScript的存在我們才需要使用一些技巧讓網(wǎng)頁加載速度更快,給用戶更好的使用體驗。
腳本阻塞
相信不管新手老手學習web制作的時候,都會被灌輸最簡單的優(yōu)化技巧,把腳本放到body底部,理由也很簡單,JavaScript會造成阻塞。
由于大多數(shù)瀏覽器使用單一的進程來處理UI的刷新與JS執(zhí)行,那么就是在一個時刻只能做一件事,只要出現(xiàn)了<script>標簽,在頁面執(zhí)行到這里的時候就會停止標簽后面的文件下載與頁面渲染動作,直到該<script>標簽內的代碼執(zhí)行完成。
加載外部JS文件也是如此,瀏覽器會等待該文件加載完成并執(zhí)行完畢后才會接著往下執(zhí)行。
現(xiàn)代瀏覽器以及IE8+基本都允許并行下載JS文件了,但是仍然會阻塞其他如圖片等資源的下載。
意思就是可以同時下載多個JS文件,腳本的下載過程不會再互相影響,但是圖片之類的仍然會受到阻塞的影響。
推薦的腳本放置位置
既然知道了腳本會阻塞UI渲染以及圖片等資源的下載,那么最簡單的自然是讓腳本放到最后執(zhí)行不就好了,盡可能的將<script>標簽放到body標簽的底部。
減少腳本數(shù)量與限制HTTP請求數(shù)
腳本數(shù)量越多自然越慢,那么自然可以采取減少腳本數(shù)量的方式,外鏈的腳本與內嵌腳本數(shù)量盡量較少,HTML解析過程中遇到script標簽都會進入執(zhí)行,數(shù)量多的話自然就會產(chǎn)生額外的時間消耗。
內嵌腳本盡量合并到一個script標簽內;
外鏈腳本與內嵌有一個網(wǎng)絡請求的區(qū)別,我們知道每個網(wǎng)絡請求都會有性能開銷的,外鏈腳本數(shù)量多的話自然會產(chǎn)生更多的性能開銷,那么鑒于上述原因,減少外鏈文件數(shù)量亦是自然,這里有兩個方法:
1.本地文件合并,打包的時候將兩個或者多個文件合并成一個,現(xiàn)代JS開發(fā)時可以使用webpack和babel來實現(xiàn),es6本身帶有模塊化的方法,根據(jù)自身需求拆分合并文件即可。(當然要根據(jù)情況,不要一昧的合并大量文件,單文件過大當然也會變成問題)
2.服務器合并文件,這個方法屬于很少使用的最佳實踐,因為它是引入多個外鏈腳本的最佳實踐,卻又是被使用的最少的,就我現(xiàn)在看到的,多數(shù)網(wǎng)站沒有使用這種技術,這個方法由后端實現(xiàn),我們在發(fā)送腳本資源請求的時候不是用的URL嗎,既然后端是通過URL來相應的,那我們當然可以直接在URL中告訴服務器我需要這幾個文件,麻煩你幫我把他們合并成一個給我。當初的雅虎combo就是這么一個服務,在我們前端使用的時候只要把請求變成類似
<pre><script src="http://abc.com/combo?path/a.js&path/b.js&path/c.js"></script></pre>
然后服務器返回a,b,c三個文件合并后的文件,其實也就是把幾個需要文件名當成url params而已,具體操作由服務器來做,這樣我們就變成了只使用了一次http請求而拿到了我需要的3個文件(css也同樣適用哦)。
延遲加載執(zhí)行腳本
大型web應用毫無疑問都包含著大量的腳本文件,文件精簡與合并也有著它的局限性,單文件過大的時候我們就會選擇拆分成多個文件,畢竟單文件過大的時候下載與執(zhí)行都會占用大量的時間并且會造成阻塞,這個時候我們一般就會采取延遲加載腳本的方式,一般有以下幾種方式:
使用script標簽的defer屬性,主流瀏覽器中script標簽都支持該屬性,添加了這個屬性之后該腳本會在頁面完成后執(zhí)行,頁面完成的定義與Jquery中的$(document).ready類似,當script帶有defer的時候這個標簽放置的位置就不會影響到整體頁面渲染了,可以與圖片等其他資源并行下載,當DOM加載完成后,帶有defer的script才會被執(zhí)行。
使用動態(tài)創(chuàng)建script標簽的方式下載腳本,這個很好理解,與使用js創(chuàng)建元素一樣,我們使用js創(chuàng)建script元素標簽并設置其src等屬性再將其添加到文檔中即可。
使用XHR對象下載注入,實際上就是使用AJAX來加載外部文件,然后再動態(tài)創(chuàng)建script添加到文檔上,這個方法與上一個動態(tài)創(chuàng)建script標簽的區(qū)別在于前者直接將script標簽放到文檔中后加載文件并在完成后執(zhí)行,而后者則是先請求外部腳本,然后再將其內容設置給你新建的script對象再添加到文檔上,讓你有選擇其什么時候執(zhí)行的機會。
結語
這第一部分的內容屬于最直觀的部分,屬于最基本也是最快見效的部分,常規(guī)的web應用前端部分只要組織規(guī)劃好頁面請求、腳本加載優(yōu)化就可以大幅度提升頁面加載速度,理清網(wǎng)頁的渲染與加載順序,DOM、CSS、腳本的執(zhí)行順序與渲染影響很重要。
