高性能 js -- 无阻塞加载脚本

参考: <<高性能JavaScript>> Nicbolas C. Zakas 著

javascript代码的下载和执行过程会阻塞浏览器的其他进程, 比如页面的绘制, 遇到<script>标签的时候都必须停下来等待代码的下载并执行. 然后才继续处理其他部分. 

无阻塞加载javascript代码的推荐方式:

1 // 将下面的这段加载代码放到</body>的闭合标签之前,这样确保了JS执行过程中不会阻碍页面的其他
2 // 内容显示, 其次第二个js文件完成下载时, 应用所需要的DOM结构已经创建完成, 并做好了交互的准备,
3 // 从而可以避免检测 winodw.onload事件.  (注: loader.js中存放的是loadScript()的实现)
4 <script type="text/javascript" src="loader.js"></script>
5 <script type="text/javascript">
6     loadScript("the-rest.js",function(){
7         app.init();
8     });
9 </script>

也可以将loadScript 直接嵌入页面, 从而避免多产生一次HTTP请求

 1 function loadScript(url,callback){
 2     var script = document.createElement("script");
 3     script.type = "text/javascript";
 4     if(script.readyState){//for IE
 5         script.onreadystatechange = function(){
 6             if(script.readyState == "onload" ||
 7                script.readyState == "complete"){
 8                 script.onreadystatechange = null; //删除事件处理器, 避免重复调用,IE自身的问题
 9                 callback();
10             }
11         }
12     }else{ // for other browser,<script>标签的onload事件.
13         script.onload = function(){
14             callback();
15         };
16     }
17     script.src = url;
18     document.getElementByTagName("head")[0].appendChild(script);
19 }

如果需要按照顺序下载js文件,可以这样调用loadScript. 更好的方式是按顺序放到一个文件中, 避免多次HTTP请求.

1 // load in order, but better way is write all script in one file in order.
2 loadScript("file1.js",function(){
3     loadScript("file2.js",function(){
4         loadScript("file3.js",function(){
5             console.log("All files are loaded in order!");
6         });
7     });
8 });

其他无阻塞模式:

1. 使用defer: 很多浏览器目前不支持(包括chrome)  

  -----  当一个带有defer属性的js文件下载时, 不会阻塞浏览器的其他进程; 无论是内嵌的还是外联的defer的js脚本, 在DOM加载完成之前都不会被执行.

2. 动态脚本元素: 返回的代码通常会立即执行, 在代码包含其他接口调用时会带来问题(可以跟踪<script>节点的onload或readystatechange事件).

  -----  文件在元素被添加到页面时开始下载; 无论在何时启动下载和执行过程不会阻塞页面其他进程, 推荐 append 到 head 下面.

1 var script = document.createElement("script");
2 script.type = "text/javascript";
3 script.src = "file1.js";
4 document.getElementByTagName("head")[0].appendChild(script);

3. 使用XMLHttpRequest

  -----  代码是在<script> 标签之外返回的(xhr的open), 下载之后不会立即执行. 浏览器兼容性好. 但是必须要求js文件与页面处于同一个域中.

4. 使用第三方库

  -----  LazyLoad:   loadScript()的增强版本

1 <script type="text/javascript" src="lazyload-min.js"></script>
2 <script type="text/javascript">
3     LazyLoad.js(['first-file.js','second-file.js'],function(){
4         Application.init();
5     });
6 </script>

  -----  LABjs  :  提供对加载过程的更精细的控制, 并试图下载尽可能多的代码

1 <script type="text/javascript" src="lab.js"></script>
2 <script type="text/javascript">
3     $LAB.script("first-file.js").wait()   //wait在这里保证按序执行
4         .script('the-rest-files.js')
5         .wait(function(){ // 下载完成后执行的函数
6             Application.init();
7         });
8 </script>
原文地址:https://www.cnblogs.com/roger9567/p/5082709.html