跳到主要內容

Even Faster Web Site 讀後

這本書寫的時間點比較早
而最近幾年的browser和網路建設更是日新月異
有些內容可能已經不大適用,不過裡面的多數準則依然可以遵守
一部分的內容在blog其它文章提過了,就不寫在這裡了

追求效率的重點之一便是提高檔案的下載、重繪(render)等處理的效率
很多技巧都是為了追求這個要點而發展出來的

*
在 import javascript 時,較舊版的瀏覽器的處理方式會是
        file1.js                     file2.js
下載    >  解析    >   下載    >  解析

過程中解析JavaScript檔案時,會停止其他檔案的下載與頁面的繪製
有幾種方式可以進行JavaScript檔案的並行下載

首先是利用XHR(XMLHttpRequest)下載
 XHR本身的運作方式就是另一條執行緒
透過他將取得的內容用 Eval() 來處理是一種方式
另一種方式則是將取得的內容透過建立DOM element的方式處理
後者的方式會比前者效率好一些,畢竟Eval是效率滿差的method
要注意的是XHR必然會受到CORS(Cross-origin resource sharing)的限制
還有就是script的執行順序不固定

第二種方式是利用Iframe下載JavaScript
下載完後透過 parentWinodw 等關聯將JavaScript檔在原本頁面執行
不過要用這個方式也會受到CORS的限制
另外在Iframe完成下載前,瀏覽器在原本頁面會顯示讀取中的忙碌狀態

第三種方式是直接建立DOM script element的方式引入
不少瀏覽器支援這樣的處理方式,但也是有些瀏覽器是不能以此方式進行並行下載
此外也有一種方式很類似,就是用document.write()新增script,受到的限制也大致相同

最後一種方式則是透過script的 defer / async 屬性處理
<script src="demo.js" defer ></script>
延遲下載,script會在背景下載而不影響頁面的繪製
並在頁面解析完成後(DOMContentLoaded事件)執行

<script src="demo.js" async ></script>
非同步下載,這是HTML5的屬性,script會在背景下載而不影響頁面的繪製
在script下載完成後立刻執行

defer 是HTML4.01起就有,如果要追求相容性,可以同時在script tag裡加上這兩種屬性
瀏覽器會以async優先採用


撰寫時注意script  tag最好優先於CSS tag
因為JavaScript有可能有變動DOM內容,如此也會導致畫面重繪製

*
JavaScript的撰寫則有一些細節可以注意

try ... catch ... 的錯誤防範機制會為這部分的程式提供多一層的Stack,以便發生錯誤時能復原
也因此寫在這個區塊內的內容會耗費較多的資源
能不必寫在裡面的程式就不要寫在裡面

而如果你會引用特定的全域變數或引數超過一次,你可以將它儲存成區域變數來增進存取效率
程式中若呼叫鏈較長時(如:a.b.c()),存取的深度較長也會導致較差的效率
這個部分在迴圈處理時會較明顯,也可以將相同的存取部分儲存成區域變數處理

if ... else ... / switch / array 的使用時機區分

如果資料能輕易被區分成不同區間,建議使用if else的方式處理
例如:
if (v > 9) {
    if (v < 7) {
      ...
    } else {
       ...
    }
} else if (v > 4) {
    ...
} else {

}

你可以注意到在這個情況下,我們能在較少的比較次數內歸納出要執行的區間

switch case 的形式適用在線性比較,且比較案例大約在10個左右的處理
寫在 switch 區塊內的變數只會被取出一次,並用來比對各個案例
相較於if else的寫法,會少掉這個用來比較的變數被取出的次數

至於更大量的比較,建議可以利用Array處理
透過index的使用更快地找出要執行的區間

以上的撰寫注意事項不僅適用於JavaScript,寫其他語言也一樣要注意
接下來是僅適用JavaScript的細節(或在其他語言有出入)

for in 因為還需要解析屬性(prototype chain),所以會比一般陣列迴圈還慢

如果回圈內的項目少時,去除迴圈實際上會比較快
例如 methodA();methodA(); 這樣寫法的效率會比用迴圈方式撰寫更快
適用此現象的項目數量大約是小於8個

迴圈常常是javascript的瓶頸,要最佳化時可以多著墨於此

*
DOM是JavaScript中最耗資源的部分
甚至是HTML Object Collection在進行迴圈遞迴的效率也比一般陣列慢,原因同 for in 迴圈
所以若要加速HTML Object的遞迴,可以先將Object另存於一般陣列變數裡

Iframe更是所有DOM element裡最耗費資源的一種
而且它的讀取行為可能會延遲到母頁面的 onload 等事件的執行時間
所以能不用就盡量不用

*
網站的網域層次劃分也是一個重點
可能比較少人會注意瀏覽器會限制能從一個網域層次下載的檔案數量
在規劃網域時,可以是頁面內的檔案來源選擇劃分的層次數量

留言