今天碰到一個(gè)大坑,分享一下。
項(xiàng)目中首頁(yè)用了一個(gè)什么安全聯(lián)盟標(biāo)志,具體用處不大,就是逼格顯得高一點(diǎn)點(diǎn)。我們?cè)瓉?lái)是這么用的。
<a key ="" logo_size="124x47" logo_type="business" >
<script src="http://static.anquan.org/static/outer/js/aq_auth.js"></script>
</a>
然后今天突然發(fā)現(xiàn),這個(gè)js加載需要30多秒,直接阻塞了之后的html以及js加載。整個(gè)頁(yè)面就在那兒白屏了整整30多秒,然后才加載了出來(lái)。(還好這是一個(gè)首頁(yè),說(shuō)實(shí)話平時(shí)瀏覽的人不是特別多,但是也算是重要門戶,后來(lái)緊急先把這個(gè)功能先下了)
大家討論了一下,這種外部引用又不算是特別重要的東西,一定要用異步。
坑又來(lái)了,這段js代碼,中間用了document.write,異步加載寫不進(jìn)去東西直接報(bào)錯(cuò)。
嘗試了以下幾種方案:
1、在script標(biāo)簽直接加上async="true"
2、在頁(yè)面末尾位置將這個(gè)a標(biāo)簽直接append進(jìn)去(首頁(yè)有很多動(dòng)畫效果,引用過jquery)
3、script標(biāo)簽不加src,而是在js中動(dòng)態(tài)加載src
以上方法都是異步方法。均直接報(bào)錯(cuò)。
后來(lái)找到了一種方法:
讓document.write的廣告無(wú)阻塞的加載 - 雨夜帶刀
這篇文章使用了一種方法,利用textarea的延遲渲染和對(duì)document.write的重寫,實(shí)現(xiàn)異步配合document.write的方案。
// html部分
<a key ="" logo_size="124x47" logo_type="business" >
<textarea id="aTextarea" style="display:none">
<script src="http://static.anquan.org/static/outer/js/aq_auth.js"></script>
</textarea>
</a>
// js部分
var loadScript = function( elem ){
var url = elem.value.match( /src="([\s\S]*?)"/i )[1],
parent = elem.parentNode,
docWrite = document.write, // 緩存原生的document.write
script = document.createElement('script'), // 創(chuàng)建一個(gè)新script來(lái)加載
head = document.head || document.getElementsByTagName('head')[0] || document.documentElement;
// 重寫document.write
document.write = function(text){
parent.innerHTML = text;
};
script.type = 'text/javascript';
script.src = url;
script.onerror =
script.onload =
script.onreadystatechange = function(e){
e = e || window.event;
if(!script.readyState || /loaded|complete/.test(script.readyState) || e === 'error'){
// 恢復(fù)原生的document.write
document.write = docWrite;
head.removeChild(script);
// 卸載事件和斷開DOM的引用
// 盡量避免內(nèi)存泄漏
head =
parent =
elem =
script =
script.onerror =
script.onload =
script.onreadystatechange = null;
}
};
// 加載script
head.insertBefore(script, head.firstChild);
};
loadScript(document.getElementById("aTextarea"));