1. 程式人生 > 實用技巧 >非同步載入指令碼

非同步載入指令碼

非同步載入指令碼

說明

兩種非同步形式

速度對比

同步方式:

非同步方式async="defer":

非同步方式async="async":

流行的兩種非同步載入庫

script.js

載入單個指令碼

載入多個指令碼

按指定順序載入多個指令碼

load.js

說明

通常我們寫頁面的時候都是將一些需要引入的js包都放到dom的最後【達到延遲載入的目的】,這樣可以快速的渲染頁面。這樣的方式去載入js是同步載入的(dom解析是同步的),何不使用非同步的方式去載入js?這樣載入時間僅僅取決於最大那個js檔案的時間,豈不是更快?

非同步載入的重要性【這是因為頁面速度成為google搜尋演算法中排名因素的時代已經到來,和競爭物件相比,你的網站載入速度越快,它在google搜尋結果列表中排名就越靠前。如果你的頁面上有廣告,那麼非同步載入會扮演重要角色】:

https://www.adglare.com/kb/4/why-is-asynchronous-ad-loading-so-important

兩種非同步形式

如果 async="async":指令碼相對於頁面的其餘部分非同步地執行(當頁面繼續進行解析時,指令碼將被執行)【對於jQuery不適合,因為jQuery可能會有dom操作】

如果不使用 async 且 defer="defer":指令碼將在頁面完成解析時執行

如果既不使用 async 也不使用 defer:在瀏覽器繼續解析頁面之前,立即讀取並執行指令碼

速度對比

同步方式:

<script src="../static/jquery/jquery-1.9.1.min.js"></script>
<img src="images/1.jpg" alt="">
<img src="images/2.jpg" alt="">
<img src="images/3.jpg" alt="">
<img src="images/4.jpg" alt="">

右側豎直藍色線表示大約在420msDOM就緒,紅色豎直線表示大約在458ms所有檔案載入就緒。

非同步方式async="defer":

<script src="../static/jquery/jquery-1.9.1.min.js" async="defer"></script>
<img src="images/1.jpg" alt="">
<img src="images/2.jpg" alt="">
<img src="images/3.jpg" alt="">
<img src="images/4.jpg" alt="">

右側豎直藍色線表示大約在355msDOM就緒,紅色豎直線表示大約在568ms所有檔案載入就緒。

非同步方式async="async":

<script src="../static/jquery/jquery-1.9.1.min.js" async="async"></script>
<img src="images/1.jpg" alt="">
<img src="images/2.jpg" alt="">
<img src="images/3.jpg" alt="">
<img src="images/4.jpg" alt="">

右側豎直藍色線表示大約在340msDOM就緒,紅色豎直線表示大約在528ms所有檔案載入就緒。

以上三種方式對比可以發現,使用非同步的方式明顯提高了DOM渲染的速度!

這是在online條件下測試的,如果在網速慢得情況下測試將更明顯,你可以把online切換完Slow 3G測試。

流行的兩種非同步載入庫

國外:script.js 國內:load.js

script.js

1,627個位元組,不推薦】

第一步:先按照這個依賴包

bower install script.js --save

第二步:讀README.md檔案,學習用法

載入單個指令碼

<body>
<script src="bower_components/script.js/dist/script.js"></script>
<script>
   // 載入單個指令碼
   $script('bower_components/jquery/dist/jquery.js', function () {
      // foo.js is ready
      console.log(jQuery);
   })
</script>
</body>

控制檯:

可見,script.js是在head標籤裡建立了一個script標籤,將load完的指令碼引入。

載入多個指令碼

<body>
<script src="bower_components/script.js/dist/script.js"></script>
<script>
   // 載入多個指令碼
   $script([
         'bower_components/angular/angular.js',
         'bower_components/angular-route/angular-route.js',
         'components/jsonp/jsonpSev.js',
         'app.js',
   ],function () {
      console.log(angular);
   })
</script>
</body>

雖然頁面中我們是引入了所有的指令碼:

但是後臺卻報了錯誤:

由於是非同步載入,肯定有先載入完和後加載完,如果先載入完的指令碼依賴後加載完的指令碼,就像jQuery-plugins.js依賴jQuery.js一樣,你要先把jQuery.js放在前面載入,然後才能載入jQuery-plugins.js,不然就會報錯!

按指定順序載入多個指令碼

// 按指定順序載入多個指令碼
$script('bower_components/angular/angular.js', function () {
   $script('bower_components/angular-route/angular-route.js', function () {
      $script('components/jsonp/jsonpSev.js', function () {
         $script('app.js', function () {
            $script('moviecat/controller.js', function () {
                console.log(123);
             })
         })
      })
   })
});

這樣並沒有解決我的問題啊?控制檯還是報錯,而且這寫法麻煩!

解決辦法:使用angular-loader.js,只要引入這個包,它就會幫我們自動的按照依賴順序載入這些包。

<body ng-app="MyApp">
<script src="bower_components/script.js/dist/script.js"></script>
<script src="bower_components/angular-loader/angular-loader.js"></script>
</body>
<script>
   // 載入多個指令碼
   $script([
         'bower_components/angular/angular.js',
         'bower_components/angular-route/angular-route.js',
         'components/jsonp/jsonpSev.js',
         'app.js',
         'moviecat_list/controller.js',
   ],function () {
      console.log(angular);

      /*手動引導的方式*/
      // angular.bootstrap(document.querySelector("[ng-app='MyApp']"),['MyApp'])
   });
</script>

load.js

1,641 位元組,推薦】

github使用文件:https://github.com/muicss/loadjs

<body ng-app="MyApp">
<script src="bower_components/loadjs/dist/loadjs.js"></script>
<script>
   // 載入多個指令碼
   loadjs([
      'bower_components/angular/angular.js',
      'bower_components/angular-route/angular-route.js',
      'components/jsonp/jsonpSev.js',
      'app.js',
      'moviecat_list/controller.js',
   ],{
      success: function() {
         console.log(123);
      },
      error:function () {
         console.log(456);
      },
      async: false // 並行獲取檔案,並序列載入他們
   });
</script>
</body>