JavaScript的加载性能优化
无论当前JavaScript代码是内嵌还是还是在外链文件中,页面的下载和渲染都必须停下来等待脚本执行完成。JavaScript执行过程耗时越久,浏览器等待响应用户输入的时间就越长。我们可以从以下几个方面进行优化:
1. 改变脚本的位置
因为脚本的下载和执行,会阻塞其他资源(样式文件或图片)的下载。因此,将<script>标签尽量尽可能放到<body>标签的底部。
2. 组织脚本
尽量减少页面中的<script>标签;
尽量将多个js文件合并为一个,减少http的请求;
3. defer, async
Html4为<script>标签定义了一个扩展属性defer。对应的<script>所对应的文件在解析到时开始下载,直到DOM元素加载完成后执行。
Html5为<script>标签定义了一个扩展属性async。对应的<script>所对应的文件在解析到时开始下载,下载完成后立即执行。
4. 动态创建<script>元素下载并执行JavaScript.
FireFox, Chrome,Safari,Opera会在下载完成后发出一个onload事件.
var script = document.createElement ("script") script.type = "text/javascript"; //Firefox, Opera, Chrome, Safari 3+ script.onload = function(){ alert("Script loaded!"); }; script.src = "script1.js"; document.getElementsByTagName("head")[0].appendChild(script);
IE实现了另一种实现方式,它会发出readystatechange事件。<script>元素有一个readyState属性,它的值随着下载外部文件的过程而改变。
var script = document.createElement("script")
script.type = "text/javascript"; //Internet Explorer
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange = null;
alert("Script loaded.");
}
};
script.src = "script1.js";
document.getElementsByTagName("head")[0].appendChild(script);
为了屏蔽浏览器的不同,可以写一个函数进行封装:
function loadScript(url, callback){ var script = document.createElement ("script") script.type = "text/javascript"; if (script.readyState){ //IE script.onreadystatechange = function(){ if (script.readyState == "loaded" || script.readyState == "complete"){ script.onreadystatechange = null; callback(); } }; } else { //Others script.onload = function(){ callback(); }; } script.src = url; document.getElementsByTagName("head")[0].appendChild(script); } |
这里有一个安全问题:<script>的src属性可以设置为另外一个域的文件。这里似乎有一个安全性的问题。
5. 使用XMLHttpRequest对象
创建一个XMLHttpRequest对象下载JavaScript文件,接着用一个动态<script>标签将JavaScript代码注入页面。
var xhr = new XMLHttpRequest(); xhr.open("get", "script1.js", true); xhr.onreadystatechange = function(){ if (xhr.readyState == 4){ if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){ var script = document.createElement ("script"); script.type = "text/javascript"; script.text = xhr.responseText; document.body.appendChild(script); } } }; xhr.send(null);
这个方法可以下载不立即执行的JavaScript. 这个代码适用于所有的浏览器。
这个方法的主要限制是页面与JavaScript文件必须放在同一个域里,不能从CDN下载。