脚本的位置
当浏览器解析到 < script> 标签的时候,会停止解析网页的其他标签,转而先去执行 javascript 脚本代码,所以有时候将 script 标签放在 < head> 之内,对 dom 的操作会报错。当然这个也有解决方案,就是可以等待页面加载完成后再执行(使用 defer 属性,当然需要看浏览器是否支持,而且使用 defer 不会阻塞浏览器的其他进程);
<html>
<head>
<script src="./index.js" defer></script>
</head>
<body>
<div id="div"></div>
</body>
</html>
目前大部分主流是支持 javascript 并行下载的,但是在下载 javascript 过程中仍然会阻塞其他资源的下载(比如图片)。
一般而言,HTTP 请求会带来额外的性能开销,所以下载单个 100 k 的文件要比下载 4 个 25 k 的文件更快。
无阻塞的脚本
因为脚本的下载和执行会让页面渲染停滞,所以,可以等待页面渲染完成以后再加载 javascript 脚本。在实现方式上面可以使用创建动态脚本元素
var script = document.createElement("script");
script.type = "text/javascript";
script.onload = function() {
//执行脚本加载完成时的处理
};
script.src = "file.js";
document.getElementsByTagName("head")[0].appendChild(script);
更加通用的用法:
// 动态加载 js 脚本(通用型无阻塞脚本加载方案)
function loadScript(url, collback) {
var script = document.createElement("script");
script.type = "text/javascript";
// 主要是看浏览器是否支持
if (script.readyState) {
script.onreadystatechange = function() {
//主要是有些浏览器在标识最终状态时 readyState 的值是不一致的
if (script.readyState == "loaded" || script.readyState == "complete") {
//因为上面存在两种状态标识,所以为了防止执行两次
script.onreadystatechange = null;
collback();
} else {
script.onload = function() {
callback();
};
}
};
}
script.src = url;
document.getelementByTagName("head")[0].appendChild(script);
}
lab.js 也是一个开源的无阻塞脚本加载工具,可以按照用户的自定义脚本顺序去加载脚本(脚本的并行下载也不会影响用户的自定义顺序)