高性能 javascript 之无阻塞加载 script

执行javascript的代码会阻塞其他文件的下载

<script>标签每次出现都会霸道地让页面等待脚本的解析和执行,无论当前的javascript代码是内嵌还是包含在外链文件中,页面的下载和渲染都会停下来等待脚本执行完成。

例如:

<html>
	<head>
		<title>Script Example</title>
		<script type="text/javascript" src="file1.js"></script>
		<script type="text/javascript" src="file2.js"></script>
		<script type="text/javascript" src="file3.js"></script>
		<link rel="stylesheet" type="text/css" href="styles.css">
	</head>
	<body>
		<p>Hello world!</p>
	</body>
</html>

这些看似正常的代码实际上有十分严重的性能问题:在<head>中加载三个javascript文件。由于脚本会阻塞页面渲染,直到它们全部下载并执行完成后,页面的渲染才会继续。可以看下执行过程中的瀑布图:
在这里插入图片描述
由于脚本会阻塞页面其他资源的下载,因此推荐将所有的<script>标签尽可能放到body标签底部,即</body>上面。

动态脚本元素

用标准的DOM方法可以很容易的创建一个新的script元素:

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

这个新创建的script元素加载了file1.js文件。文件在该元素被添加到页面时开始下载。这种技术的重点在于:无论在何时启动,文件的下载和执行过程都不会阻塞页面其他进程。甚至可以将代码放到<head>区域不会影响页面其他部分。

推荐的无阻塞模式:

<script type="text/javascript" src="loader.js"></script>
<script type="text/javascript">
	loadScript("the-rest.js",function() {
		Application.init();
	});
</script>

把这段代码放到</body>闭合标签之前。另一种方法是将loadScript()函数直接嵌入页面,从而避免多产生一次HTTP请求。例如:

<script type="text/javascript">
	function loadScript(url,callback) {
		var script = document.createElement("script");
		script.type = "text/javascript";

		if(script.readyState) { // IE 这种基本不需要考虑了,ie 的份额很低,基本淘汰了
			script.onreadystatechange = function() {
				if (script.readyState == "loaded" || cript.readyState == "complete") {
					script.onreadystatechange = null;
					callback();
				}
			}
		}else { // 其他浏览器
			script.onload = function() {
				callback();
			}
		}
		script.src = url;
		document.getElementByTagName("head")[0].appendChild("script");
	}
	
	loadScript("the-rest.js",function(){
		Application.init();
	})
</script>

优化建议

  • </body>闭合标签前,将所有的<script>标签放到页面底部。这能确保在脚本执行前页面已经完成了渲染。

  • 合并脚本。页面中的<script>标签越少,加载也就越快,响应也更迅速。无论外链文件还是内嵌脚本都是如此。

  • 有多种无阻塞下载JavaScript的方法:

    1、使用script标签的deferasync属性,这两者的相同点是采用并行下载,在下载的过程中不会产生阻塞。区别在于执行时机,async是加载完后自动执行,而defer需要等待页面完成后执行。
    2、使用动态创建的<script>元素来下载并执行代码。
    3、使用XHR对象下载javascript代码并注入页面中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值