非同步載入指令碼
通常我們寫頁面的時候都是將一些需要引入的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="">
右側豎直藍色線表示大約在420ms後DOM就緒,紅色豎直線表示大約在458ms所有檔案載入就緒。
<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="">
右側豎直藍色線表示大約在355ms後DOM就緒,紅色豎直線表示大約在568ms所有檔案載入就緒。
<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="">
右側豎直藍色線表示大約在340ms後DOM就緒,紅色豎直線表示大約在528ms所有檔案載入就緒。
以上三種方式對比可以發現,使用非同步的方式明顯提高了DOM渲染的速度!
這是在online條件下測試的,如果在網速慢得情況下測試將更明顯,你可以把online切換完Slow 3G測試。
bower install script.js --save
<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>
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>