我注意到在我的网站的<head>
(工作)中,有很多<link rel="stylesheet" type="text/css" href="" />
和<script type="text/javascript" src="">
个标签。还有更多的JavaScript / CSS文件仅为特定页面加载(我们使用CodeIgniter,文件路径传递到标题视图)。
我正在考虑使用条件/异步加载器(例如,yepnope.js,head.js等),但我注意到这样做有一个小问题。
在我们的视图中,有内联JavaScript,有些使用$(function(){})
有些用$(document).ready(function(){})
,有些只有代码(使用jQuery),不在ready
块中。
不编辑每个视图文件以将其代码包装在函数中并在加载JS文件时调用它,是否有办法延迟内联代码直到JavaScript被异步加载?
答案 0 :(得分:28)
你实际上可以懒惰加载内联javascript: 1-将内联脚本中的type参数更改为:text / delayscript
这
<!– Inline Script –>
<script type="text/javascript" language="javaScript">
/* Code */
</script>
要
<!– Inline Script –>
<script type="text/delayscript">
/* Code */
</script>
为脚本标记提供自定义Mime类型text / delayscript强制浏览器忽略其内容(请注意,将其完全保留为text / javascript)。
2-延迟加载所有内联脚本 一旦heads.js(或者您可能正在使用的其他框架)确认它延迟加载了所有外部JS,您就可以获取所有自定义脚本标记的内容并将其注入页面中:
<script>
head.ready(function() {
var
_head = document.getElementsByTagName("head")[0],
_script = document.createElement('script'),
_scripts = document.getElementsByTagName("script"),
_txt = "text/delayscript",
_contents = []
;
for(var i=0,l=_scripts.length;i<l;i++){
var _type = _scripts[i].getAttribute("type");
if(_type && _type.toLowerCase() ==_txt)
_contents.push(_scripts[i].innerHTML)
}
_script.type = 'text/javascript';
_script.innerHTML = _contents.join(" ");
_head.appendChild(_script);
});
为了更加优雅,您可以将内联脚本保留在DOM树中的原始层次结构中,而不是像上面所建议的那样将所有内容都插入到一个脚本中,方法是将标记的内联脚本标记替换为新的一个有mime类型的文本/ javascript:
head.ready(function() {
var
_scripts = document.getElementsByTagName("script"),
_doc = document,
_txt = "text/delayscript"
;
for(var i=0,l=_scripts.length;i<l;i++){
var _type = _scripts[i].getAttribute("type");
if(_type && _type.toLowerCase() ==_txt)
_scripts[i].parentNode.replaceChild((function(sB){
var _s = _doc.createElement('script');
_s.type = 'text/javascript';
_s.innerHTML = sB.innerHTML;
return _s;
})(_scripts[i]), _scripts[i]);
}
});
答案 1 :(得分:5)
您必须考虑将内联代码移到“外部”并将其包含在
中<script defer="defer" type="text/javascript" src="">
答案 2 :(得分:2)
首先,我建议您非常仔细地分析客户端脚本的加载,而不仅仅是第一次加载JavaScript,而是第二次加载相同的JavaScript文件或加载另一个JavaScript文件。页。如果Web服务器在脚本上正确设置了ETag,或者您使用HTTP的其他缓存选项(请参阅caching tutorial了解详细信息)来获取JavaScripts文件,那么将不会加载文件本身,只会缓存重新验证将完成。因此,您所描述的问题可能并不像它看起来那么重要。
如果您决定动态加载某些脚本,可以使用jQuery.getScript并将所有相关代码放在success
回调中。如果您需要加载一个或两个JavaScript文件,那么这种方式将非常有效,但如果您需要加载具有更复杂依赖性的JavaScript文件列表,则实现可能并不那么容易。如果您可以在document.writeln
内使用<head>
。 <head>
内部方法的使用几乎没有任何缺点(详见here)。
答案 3 :(得分:2)
HTML5为具有已定义src
的脚本引入了新的async
参数。
您可以直接在任何<script>
元素上添加它:
<script src='/js/script.js' async></script>
但是:请记住,它不适用于内联脚本!
如果您的某些页面混合使用外部脚本和内联脚本,如果异步加载外部,则意味着内联脚本实际上将在之前执行异步脚本...哪个可以有不良影响。
设置此布尔属性以指示浏览器应尽可能异步执行脚本。它对内联脚本(即没有src属性的脚本)没有影响。
例如,如果您有以下配置:
<script src='/js/jquery.min.js' async></script>
<script>
// --> jQuery won't be loaded when this script will be executed!
// This will throw an error.
$(function () {
$('#element').doSomething();
});
</script>
答案 4 :(得分:1)
根据您的设置,您可能需要查看www.cloudflare.com上的服务。他们目前的测试版功能称为火箭加载器,就是这样,包括内联脚本。
这是免费服务。尝试一下;)
另外,您可以获得免费的缓存代理:)
答案 5 :(得分:1)
创建内联函数,而不是内联脚本。然后在javascript文件的末尾,调用函数(如果存在)。
function inline_script() {.. code ..}
在你的串联jquery + etc异步javascript文件中:
if (typeof(inline_script) == 'function') inline_script()
你必须进行一些改组,以确保每页只有一个inline_script,或者如果你多次调用它,可以使用某种缓存将它们组合在一起。
在当前时代,这仍然是一个有趣的问题,即使这个问题很老,异步脚本=相当棒的
答案 6 :(得分:0)
查看使用headjs。这是一个很好的轻量级库,可以为您完成所有这些。