<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    憨厚生

    ----Java's Slave----
    ***Java's Host***

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      165 隨筆 :: 17 文章 :: 90 評(píng)論 :: 0 Trackbacks
    轉(zhuǎn) http://www.cnblogs.com/yslow/archive/2009/04/29/1446236.html

    耦合異步腳本

    英文原文地址

     

    最近我的工作都是圍繞異步加載外部腳本(loading external scripts asynchronously) 展開(kāi)。當(dāng)外部腳本以普通方式加載時(shí)(<script src="...">) 會(huì)阻塞頁(yè)面內(nèi)所有其它資源的下載和腳本下方元素的渲染.你可以查看將腳本放在底部(Put Scripts at the Bottom)的樣例的效果. 異步加載腳本會(huì)避免阻塞行為進(jìn)而更快的加載頁(yè)面.

    異步加載腳本產(chǎn)生的問(wèn)題是內(nèi)嵌腳本使用外部腳本中定義的符號(hào)的問(wèn)題. 如果內(nèi)嵌腳本使用了異步加載的外部腳本符號(hào),競(jìng)爭(zhēng)條件下可能會(huì)導(dǎo)致未定義的符號(hào)錯(cuò)誤。因此有必要保證異步腳本和內(nèi)嵌腳本以下面方式進(jìn)行耦合:在異步腳本下載完畢之前內(nèi)嵌腳本不能被執(zhí)行。

    下面有幾種方式耦合異步腳本.

    • window’s onload - 內(nèi)嵌腳本可以嘗試使用窗口的onload事件. 實(shí)現(xiàn)起來(lái)非常簡(jiǎn)單,但是內(nèi)嵌腳本不會(huì)盡可能早的執(zhí)行.
    • script’s onreadystatechange - 內(nèi)嵌腳本可以嘗試使用腳本的onreadystatechangeonload 事件(在所有流行的瀏覽器里面均需要你自己來(lái)實(shí)現(xiàn)) 代碼比較長(zhǎng)而復(fù)雜,但是可以確保在腳本下載完畢之后馬上執(zhí)行內(nèi)嵌腳本.
    • hardcoded callback - 外部腳本可以修改為通過(guò)一個(gè)回調(diào)函數(shù)(callback function)來(lái)明確的調(diào)用內(nèi)嵌腳本,如果外部腳本和內(nèi)嵌腳本是一個(gè)團(tuán)隊(duì)開(kāi)發(fā)的話,這樣是沒(méi)有問(wèn)題的,但如果使用第3方的腳本,這就提供不了必要的靈活性。

    在這個(gè)博客帖子里我討論兩個(gè)問(wèn)題: 如何使用異步腳本加快頁(yè)面,如何通過(guò)Degrading Script Tags模式耦合外部腳本和內(nèi)嵌腳本. 我通過(guò)我最近剛剛完成的一個(gè)項(xiàng)目UA Profiler results sortable圖表來(lái)演示. 我還使用了Stuart Langridge的 sorttable排序腳本. 把他的腳本增加到我的頁(yè)面并排序結(jié)果耗費(fèi)了我大約5分鐘.通過(guò)增加一點(diǎn)使用異步腳本和耦合腳本的工作量我可以使這個(gè)頁(yè)面提高30%的加載速度

    普通Script標(biāo)記

    最初我使用普通的方法(<script src="...">)將Stuart Langridge的sorttable排序腳本加入到UA Profiler, 例子見(jiàn)Normal Script Tag. HTTP瀑布圖見(jiàn)圖1.

    普通Script標(biāo)記
    圖1: 普通Script標(biāo)記的瀑布圖

    表格排序工作正常,但由于它使頁(yè)面慢了許多,我并不滿意. 圖1中我們可以看到腳本(sorttable-async.js)阻塞了頁(yè)面內(nèi)唯一的后繼HTTP請(qǐng)求(arrow-right- 20X9.gif), 造成頁(yè)面加載變慢. 瀑布圖是使用Firebug 1.3 beta來(lái)產(chǎn)生的(你也可以使用httpwatch基調(diào)網(wǎng)絡(luò)webwatch工具來(lái)查看效果)。 新版本的Firebug在onload事件發(fā)生的地方標(biāo)記了一條紅豎線. (藍(lán)豎線是DOMContentLoaded事件.) 對(duì)于普通Script標(biāo)記 來(lái)說(shuō), onload 事件在第487毫秒產(chǎn)生.

    異步加載腳本

    對(duì)初始頁(yè)面渲染來(lái)說(shuō),腳本sorttable-async.js是沒(méi)有必要的 - 表格被渲染之后才會(huì)排序. 這種情況(外部腳本不會(huì)被初始頁(yè)面使用)是可以使用異步腳本加載的主要特征 . 例子異步加載腳本 使用DOM方式異步加載:

    var script = document.createElement('script');
    script.src = "sorttable-async.js";
    script.text = "sorttable.init()"; // 這會(huì)在下面解釋
    document.getElementsByTagName('head')[0].appendChild(script);

    異步加載腳本的HTTP瀑布圖見(jiàn)圖2。注意我是如何使用異步加載技術(shù)來(lái)避免阻塞行為的 - sorttable-async.js和arrow-right-20×9.gif 被同時(shí)下載. onload時(shí)間為429毫秒.

    異步加載腳本
    圖2: 異步加載腳本的HTTP瀑布圖

    John Resig介紹的 Degrading Script Tags 模式

    例子異步加載腳本使頁(yè)面加載更快了,但仍舊有進(jìn)一步提高的空間. 默認(rèn)sorttable排序是通過(guò)在onload事件中增加sorttable.init()來(lái)觸發(fā)。當(dāng)外部腳本被加載完畢后內(nèi)嵌腳本立即調(diào)用sorttable.init()能進(jìn)一步提升性能. 在這種情況下,我使用的API僅僅是一個(gè)函數(shù),但是我將嘗試一個(gè)足夠靈活的模式來(lái)支持更復(fù)雜的情況。

    前面我列出了各種內(nèi)嵌腳本和外部異步腳本耦合的方法: window’s onload, script’s onreadystatechange, 和 hardcoded callback. 這里,我使用了來(lái)自John Resig的被稱為Degrading Script Tags模式的技術(shù)。 John描述了如何耦合一個(gè)內(nèi)嵌腳本和外部腳本,例如:

    <script src="jquery.js">
    jQuery("p").addClass("pretty");
    </script>

    他提到的這個(gè)方法是使內(nèi)聯(lián)腳本在外部腳本下載完畢之后才開(kāi)始執(zhí)行。使用這種方式耦合內(nèi)嵌腳本和外部腳本有幾個(gè)好處:

    • 更簡(jiǎn)單 - 將2個(gè)script標(biāo)記替換為1個(gè)script標(biāo)記
    • 更清晰 - 內(nèi)嵌代碼依賴于外部腳本的關(guān)系更為明顯
    • 更安全 - 如果外部腳本下載失敗,內(nèi)嵌腳本就不會(huì)執(zhí)行,避免拋出未定義的符號(hào)錯(cuò)誤

    當(dāng)使用異步加載外部腳本時(shí)這也是一個(gè)很棒的模式。為了使用這個(gè)技術(shù),我必須修改我的內(nèi)嵌代碼和外部腳本. 對(duì)于內(nèi)嵌代碼, 我增加了第3行來(lái)設(shè)置 script.text的屬性. 為了耦合代碼, 我在sorttable-async.js末尾增加了如下代碼:

    var scripts = document.getElementsByTagName("script");
    var cntr = scripts.length;
    while ( cntr ) {
    var curScript = scripts[cntr-1];
    if ( -1 != curScript.src.indexOf('sorttable-async.js') ) {
    eval( curScript.innerHTML );
    break;
    }
    cntr--;
    }

    此代碼遍歷網(wǎng)頁(yè)的所有腳本,直到它找到腳本塊本身 (此時(shí)腳本的src屬性包含sorttable-async.js),然后利用eval將代碼(sorttable.init ())增加到腳本觸發(fā)運(yùn)行. (備注:雖然內(nèi)嵌代碼使用text屬性增加代碼內(nèi)容,但是需要使用innerHTML獲取代碼. 這是代碼跨瀏覽器工作的必要保證) 經(jīng)過(guò)這樣的優(yōu)化,外部腳本不會(huì)阻塞其它資源的下載,同時(shí),內(nèi)嵌代碼也會(huì)盡可能早的執(zhí)行.

    延遲加載

    通過(guò)延遲加載能更快的加載頁(yè)面 (通過(guò)onload事件動(dòng)態(tài)加載). 例如 Lazyload 是在onload 事件中包含如下代碼:

    window.onload = function() {
    var script = document.createElement('script');
    script.src = "sorttable-async.js";
    script.text = "sorttable.init()";
    document.getElementsByTagName('head')[0].appendChild(script);
    }

    這種情況絕對(duì)需要腳本耦合技術(shù),在onload事件里面的代碼sorttable.init()不會(huì)被執(zhí)行,因?yàn)榇藭r(shí)onload事件已經(jīng)發(fā)生,而sorttable-async.js還沒(méi)被下載。延遲加載的好處是使onload事件更快的發(fā)生,見(jiàn)圖3。紅豎線表明onload事件發(fā)生在第320毫秒.

    延遲加載
    圖3: 延遲加載的HTTP瀑布圖

    結(jié)論

    通過(guò)避免通常的阻塞行為,異步加載腳本和延遲加載腳本可以提高網(wǎng)頁(yè)的加載時(shí)間. 下面是增加不同版本的sorttable排序例子代碼:

    以上時(shí)間指的是onload事件發(fā)生的時(shí)間。



    posted on 2009-11-04 15:25 二胡 閱讀(239) 評(píng)論(0)  編輯  收藏 所屬分類: JS
    主站蜘蛛池模板: 高清永久免费观看| 最近的免费中文字幕视频 | 67pao强力打造67194在线午夜亚洲 | 国产精品亚洲精品日韩电影| 亚洲精品无码久久毛片| 久久九九AV免费精品| 最近最新高清免费中文字幕 | 亚洲AV无码乱码在线观看牲色| 久久性生大片免费观看性| 亚洲AV无码一区东京热久久| 毛片网站免费在线观看| 人碰人碰人成人免费视频| 久久精品国产亚洲AV嫖农村妇女| 国产免费观看a大片的网站| 久久国产乱子精品免费女| 亚洲成_人网站图片| 国产亚洲精aa成人网站| 天天摸夜夜摸成人免费视频| 最近2019中文免费字幕在线观看| 亚洲一区二区三区免费在线观看| 亚洲欧洲自拍拍偷精品 美利坚| 亚洲三级在线免费观看| 永久免费精品影视网站| 久久精品国产亚洲αv忘忧草 | 又粗又长又爽又长黄免费视频| 亚洲色图.com| 亚洲伊人成无码综合网 | 永久在线免费观看| 免费一级特黄特色大片| 国产精品亚洲片在线va| 亚洲第一AAAAA片| va亚洲va日韩不卡在线观看| 美女视频黄的全免费视频 | 亚洲人成人网站在线观看| 特级做A爰片毛片免费69| 久久国产免费观看精品| 色吊丝性永久免费看码| 亚洲精品国产高清在线观看| 亚洲欧洲日产国码在线观看| 久久精品国产亚洲香蕉| 国产精品xxxx国产喷水亚洲国产精品无码久久一区 |