JS脚本文件的位置对页面加载性能影响以及无阻塞脚本(javascript)模式

时间:2023-12-09 12:46:01

JS的阻塞特性:当<script>出现的时候,页面必须等待脚本文件的加载、解析、执行完毕后才能继续进行页面的渲染。不管脚本文件是以内联形式还是外部引入的形式出现在<script>中,页面的加载和渲染都必须停下来等待脚本文件的执行完成。因为在脚本文件中可能会修改页面的内容。这就会出现一个问题,当HTML文件中引入很多的外部脚本文件和内联脚本时,可能会导致页面的严重阻塞,影响页面的加载和渲染,用户体验特别的差。因而需要寻找适当的方法来减小脚本文件对页面加载带来的影响。

改善性能的几种方式:

1、 我们都知道脚本文件既可以存放在<head>标签中也可以存放在<body>标签中,并且是循序重复出现的如果将将本文件放在<head>中,如下:

    <!DOCTYPE html>
<html >
<head>
<meta charset="utf-8">
<title></title>
<script src="script.js"></script>
<script src="file1.js"></script>
<script src="file2.js"></script>
<script src="file3.js"></script>
<link rel="styleSheet" type="text/css" hhref="styles.css"></link>
</head>
<body onload="init()">
<p> swapCache方法示例</p>
</body>
</html>

在上述代码在<head>中加载了四个JS文件,由于脚本阻塞页面的渲染,所以只有当脚本全部下载完并执行完毕后,页面才会开始渲染,在body标签之前是不会渲染任何部分的。同时在加载JS文件时,只有当前一个加载完毕并执行完毕后才会进行下一个JS文件的加载和执行,在早期的浏览器中都是不能进行JS文件的并行下载的,不过目前很多主流的浏览器都支持异步加载JS包,但是页面渲染的其他资源如图片等,仍然或因为JS的加载而阻塞,所以通常建议将JS文件尽量放在<body>标签中,以尽量减少对整个页面下载的影响。

2、由于每个<script>标签的初始下载时都会阻塞页面的渲染,所以尽量减少<script>标签的数量有助于改善页面阻塞情况。也就是说内联JS文件尽量合并,外部引入的文件如果可以合并最好不过,通常单个下载100KB文件比下载4个25KB文件更快。

3、无阻塞脚本的秘诀在于,在页面加载完毕后才加载javascript代码,也就是说当触发window对象的onload事件后再下载脚本。有如下几种方式实现这一效果:

(1)利用属性:async/defer

async:异步加载脚本同时在脚本加载的时执行脚本,不影响页面的加载和渲染

defer:异步加载脚本同时进行页面渲染,但脚本的执行需要等到页面加载完毕

  <!DOCTYPE html>
<html >
<head>
<meta charset="utf-8">
<title></title>
<script defer>
alert("defer");
</script>
<script >
alert("script");
</script>
<script>
window.onload=function(){
alert("onload")
}
</script>
<link rel="styleSheet" type="text/css" hhref="styles.css"></link>
</head>
<body onload="init()">
<p> swapCache方法示例</p>
</body>
</html>

上述代码在不支持defer的浏览器弹出的顺序依次为:defer,script,load;在支持defer的浏览器中的弹出顺序为:script,defer,load。带有defer属性的标签是在onload的事件执行之前执行的,也即当页面加载完后执行带有defer属性的<script>中大JS代码。但是加载与页面加载异步执行的。

(2)利用动态脚本元素即通过document.createElement("script")动态生成脚本

   var script=document.craateElement("script");
script.type="text/script"
script.src="file.js";
docuemnt.getElementsByTagName("head")[0].appendChild("script");

这种方法的优势在于无论什么时候启动加载,问价的下载和执行都不会阻塞页面的其他进程。该方法具有挂浏览器的兼容性和易用性优势,是最为通用的无阻塞加载的解决方法。

(3)XMLHttpRequest脚本注入的方法

利用XHR对象,借助它进行javascript脚本的下载,最后通过动态创建<script>元素将代码注入到页面当中

var xhr=new XMLHttpRequest();
xhr.open("get","file.js",true);
xhr.onreadystatechange=function(){
if(xhr.state==4&&xhr.status==200)
var script=docuemnt.createElement("script");
script.type="text/script";
script.text=xhr.reaponseText;
document.body.appendChild(script);
}