延迟加载JavaScript和内联JavaScript

时间:2012-01-20 19:18:35

标签: javascript codeigniter asynchronous

我注意到在我的网站的<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被异步加载?

7 个答案:

答案 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。这是一个很好的轻量级库,可以为您完成所有这些。