加載 Javascript 最佳實踐
相信很多與頁面打過交道的同學都對 Yahoo 的 Best Practices for Speeding Up Your Web Site 不陌生。而這 35 條最佳實踐中,對 Javascript 的加載順序的要求是:Put Scripts at the Bottom。因為根據(jù) HTTP/1.1 specification 看來,在同一時間加載兩個文件是最理想的,而 Javascript 腳本會阻礙平行下載。Steve 說那是 2008 – 2009 那個時代用的。現(xiàn)在,加載 Javascript 已經有了革命性的化變。
在開講之前,有一個必須解決的問題是:為什么我們要把 JS 文件放在 </body> 之前的最底部。根本原因是,它不能平行下載。而其實并不是所有瀏覽器都不支持。現(xiàn)在大部分瀏覽器都支持 Script 的平行下載,除了老掉牙的 IE6&7、Firefox 2&3.0、 Safari 3、Chrome 1。但我們最熟悉的老掉牙同學 IE6 (或以IE為核的那些殼)還是中國(甚至世界上)市場上占用率最高的瀏覽器,因此我們需要一個折衷的方案。
一、分析
我們有6種方法可以實現(xiàn)平行(NON-Blocking)下載:
- XHR Eval – 用 XHR 下載,并
eval()
執(zhí)行 responseText.。 - XHR Injection – 用 XHR 下載,在頁面中動態(tài)創(chuàng)建一個 script 元素,并將 responseText 作為其 text 。
- Script in Iframe – 把腳本放在 HTML 中,使用 ifame 來下載它。
- Script DOM Element – 動態(tài)創(chuàng)建一個 script 元素,把
src
指向腳本URL. - Script Defer – 給 script 標添加
defer
屬性 document.write
Script Tag – 利用document.write
把<script src="">
添加到 HTML 中。但這個只對 IE 有效。
兼容性可看下圖:
Technique | Parallel Downloads | Differ | Existing Scripts | Busy Indicators | Ensures Order | Size (bytes) |
---|---|---|---|---|---|---|
XHR Eval | IE, FF, Saf, Chr, Op | no | no | Saf, Chr | - | ~500 |
XHR Injection | IE, FF, Saf, Chr, Op | no | yes | Saf, Chr | - | ~500 |
Script in Iframe | IE, FF, Saf, Chr, Op | no | no | IE, FF, Saf, Chr | - | ~50 |
Script DOM Element | IE, FF, Saf, Chr, Op | yes | yes | FF, Saf, Chr | FF, Op | ~200 |
Script Defer | IE, Saf4, Chr2, FF3.1 | yes | yes | IE, FF, Saf, Chr, Op | IE, FF, Saf, Chr, Op | ~50 |
document.write Script Tag | IE, Saf4, Chr2, Op | yes | yes | IE, FF, Saf, Chr, Op | IE, FF, Saf, Chr, Op | ~100 |
二、方案
對于究竟應該使用哪種方案。這完全取決于你需要自身的需要。這張圖描述了什么時候使用什么方法:
從總體上看來,Script DOM Element 是比較好的方案。NCZ 的博客上提過,目前最好的技術是:
- 創(chuàng)建兩個 JavaScript 文件。第一個文件只提供動態(tài)下載 Javascript 的代碼,第二個文件則包含所有其他頁面所需腳本的文件。
- 像
<script>
在頁部(</body> 之前)引入第一個文件。 創(chuàng)建第二個 <script>
來執(zhí)行下載第二個 Javascript 文件的函數(shù)和其他的初始化代碼。
三、實現(xiàn)代碼
根據(jù)上面的提到的技術。NCZ 推薦第一個文件只包含相應的實現(xiàn)第二個文件動態(tài)加載的代碼:
function loadScript(url, callback){
var script = document.createElement("script")
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" ||
script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function(){
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
然后,我們可以在頁面中這樣做:
<script type="text/javascript" src="http://your.cdn.com/first.js"></script>
<script type="text/javascript">
loadScript("http://your.cdn.com/second.js", function(){
//初始化你的代碼
});
</script>
在 HTML5 上,我們可以使用 async 屬性。這個 HTML 屬性的作用正是我們需要的 NON-Blocking 下載技術。雖然目前支持的瀏覽器并不多(似乎只有 Firefox 3.6+ ?),但給需要平行下載的 Javascript(按照方案看來,一般是第一個 JS 文件) 加上這個屬性,也不會影響其他不支持的瀏覽器,所以,是推薦使用的。
四、實踐
YUI3 的 Loader 使用了 NCZ 的這樣的方法。而在支付寶。我們也使用了類似的方法。這里簡單說一下。
<script type="text/javascript" charset="utf-8">
// 配置 combo 服務的 PATH
araleConfig = {
combo_host: "http://domain.com",
combo_path: '/path/to/the/compressed/file'
}
</script>
<script type="text/javascript" src="core.js"></script>
在使用的時候,再利用 Loader.use() 來實現(xiàn)代碼的動態(tài)加載。當然,這里不僅僅是動態(tài)加載,還有一定的緩存機制在里面。建議你查看相關的 combo 服務的技術。目前支付寶前端架構組的工友們,已經在這一塊取得了一些不錯的進展(根據(jù)測試報告,速度是非常不錯的,可能會在適當?shù)臅r候開源出來)。
五、總結
前端性能優(yōu)化方面。還有很多東西可以做。并且,隨著 HTML5 技術的出現(xiàn)和 Javascript 技術的不斷創(chuàng)新,相信還有更多東西是值得期待。前端們,加油吧,未來有很多東西應該是由你來主導的。
Reference:
相關文章
Bootstrap導航菜單點擊后無法自動添加active的處理方法
今天小編就為大家分享一篇Bootstrap導航菜單點擊后無法自動添加active的處理方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08JS,Jquery獲取select,dropdownlist,checkbox下拉列表框的值(示例代碼)
本篇文章主要是對JS,Jquery獲取select,dropdownlist,checkbox下拉列表框的值(示例代碼)進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助2014-01-01javascript通過className來獲取元素的簡單示例代碼
本篇文章主要是對javascript通過className來獲取元素的簡單示例代碼進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助2014-01-01基于JavaScript實現(xiàn)數(shù)值型坐標軸刻度計算算法(echarts的y軸刻度計算)
這篇文章主要介紹了基于JavaScript實現(xiàn)數(shù)值型坐標軸刻度計算算法(echarts的y軸刻度計算),文章圍繞主題展開詳細的內容介紹,感興趣的朋友可以參考與一下2022-06-06In Javascript Class, how to call the prototype method.(three
In Javascript Class, how to call the prototype method.(three method)...2007-01-01