執行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
標籤的defer
或async
屬性,這兩者的相同點是採用並行下載,在下載的過程中不會產生阻塞。區別在於執行時機,async
是加載完後自動執行,而defer
需要等待頁面完成後執行。
2、使用動態創建的<script>
元素來下載並執行代碼。
3、使用XHR
對象下載javascript
代碼並注入頁面中。