延迟加载 JavaScript 和内联 JavaScript

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8946715/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 05:06:56  来源:igfitidea点击:

Lazy loading JavaScript and Inline JavaScript

javascriptcodeigniterasynchronous

提问by Rocket Hazmat

I noticed in the <head>of my site (for work), there are a lot of <link rel="stylesheet" type="text/css" href="" />and <script type="text/javascript" src="">tags. There are even more JavaScript/CSS files that are only loaded for specific pages (we're using CodeIgniter, and the file paths are passed to the header view).

我注意到在<head>我的网站(工作)中,有很多<link rel="stylesheet" type="text/css" href="" /><script type="text/javascript" src="">标签。还有更多只为特定页面加载的 JavaScript/CSS 文件(我们使用的是 CodeIgniter,文件路径被传递到标题视图)。

I was considering using a conditional/asynchronous loader (eg. yepnope.js, head.js, etc.), but I noticed a small problem with doing this.

我正在考虑使用条件/异步加载器(例如 yepnope.js、head.js 等),但我注意到这样做的一个小问题。

In our views, there is inline JavaScript, some uses $(function(){})some uses $(document).ready(function(){}), and some just has code (using jQuery) that's not in a readyblock.

在我们的视图中,有内联 JavaScript,有些使用$(function(){})某些 uses $(document).ready(function(){}),而有些只包含不在ready块中的代码(使用 jQuery)。

Without editing EVERY view file to wrap its code in a function and calling that when the JS files are loaded, is there a way to delay the inline code until the JavaScript is asynchronously loaded?

无需编辑每个视图文件以将其代码包装在一个函数中并在加载 JS 文件时调用它,有没有办法延迟内联代码,直到异步加载 JavaScript?

回答by YoussefTaghlabi

You can actually lazyload inline javascript: 1- Change the type parameter in the inline script to: text/delayscript

您实际上可以延迟加载内联 javascript:1- 将内联脚本中的类型参数更改为:text/delayscript

FROM

    <!– Inline Script –>
<script type="text/javascript" language="javaScript">
             /* Code */
</script>

To

    <!– Inline Script –>
<script type="text/delayscript">
             /* Code */
</script>

Giving the script tag a custom Mime type text/delayscript forces the browser to ignore its content (Please note that leaving it out entirely will default to text/javascript).

给脚本标签一个自定义的 Mime 类型 text/delayscript 强制浏览器忽略它的内容(请注意,完全忽略它会默认为 text/javascript)。

2- Lazy load all inline scripts Once heads.js (Or an other framework you might be using) confirms that it lazy loaded all your external JS, you can then grab the content of all your custom script tags and inject them in the page:

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);

});

To be even more graceful, you can actually keep the inline scripts in their original hierarchy in the DOM tree instead of jamming all their content in one script, as I have suggested above, by replacing the marked inline script tag by a new one that has mime type text/javascript:

为了更加优雅,您实际上可以将内联脚本保留在 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]);
}
});

回答by Salaros

You have to consider moving inline code "outside" and include it with

您必须考虑将内联代码移到“外部”并将其包含在

<script defer="defer" type="text/javascript" src="">

回答by Oleg

First of all I would recommend you to analyse the loading of the scripts on the client side very carefully and not only for the first JavaScript loading, but on the loading of the same JavaScript files at the second time or its loading on another page. If the ETag are correctly set on the scripts by the web server or if you use other caching options of HTTP (see the caching tutorialfor details) for the JavaScripts files than no loading of the files itself will take place and only the cache revalidation will be done. So it can be that the problem which you describes is not so important like it looks like.

首先,我建议您非常仔细地分析客户端脚本的加载,不仅针对第一次 JavaScript 加载,还针对第二次加载相同的 JavaScript 文件或在另一个页面上加载。如果 Web 服务器在脚本上正确设置了 ETag,或者如果您对 JavaScript 文件使用 HTTP 的其他缓存选项(有关详细信息,请参阅缓存教程),则不会加载文件本身,只会进行缓存重新验证完成。因此,您描述的问题可能不像看起来那么重要。

If you do decide to load some scripts dynamically you can use jQuery.getScriptand place all dependent code inside of the successcallback. If you need to load one or two JavaScript files the way will work very good, but if you need to load a list of JavaScript files with more complex dependency the implementation could be not so easy. In the case you can use document.writelninside of <head>. The usage of the method inside of <head>has almost no disadvantages (see herefor details).

如果您决定动态加载一些脚本,您可以使用jQuery.getScript并将所有相关代码放在success回调中。如果您需要加载一两个 JavaScript 文件,这种方式会很有效,但如果您需要加载具有更复杂依赖项的 JavaScript 文件列表,则实现可能并不那么容易。在这种情况下,您可以document.writeln<head>. 内部方法的使用<head>几乎没有缺点(详见这里)。

回答by Flo Schild

HTML5 introduced a new asyncparameter for scripts having a defined src.

HTML5async为具有定义的src.

You can add it directly on any <script>element :

您可以将它直接添加到任何<script>元素上:

<script src='/js/script.js' async></script>

BUT : keep in mind that it will not work on inline scripts!

但是:请记住,它不适用于内联脚本!

And if your some of your pages mix either external and inline scripts, if you load the external asynchronously, it means that the inline scripts will actually be executed beforethe asynchronous ones... Which can have unwanted effects.

如果你的一些页面混合了外部和内联脚本,如果你异步加载外部,这意味着内联脚本实际上会异步脚本之前执行......这可能会产生不良影响。

Set this Boolean attribute to indicate that the browser should, if possible, execute the script asynchronously. It has no effect on inline scripts (i.e., scripts that don't have the src attribute).

设置此布尔属性以指示浏览器应在可能的情况下异步执行脚本。它对内联脚本(即没有 src 属性的脚本)没有影响。

For instance, if you have the following configuration :

例如,如果您有以下配置:

<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>

回答by Michael S?rensen

Depending on your setup, you might want to look into the service from www.cloudflare.com. Their current beta functionality called rocket loader, does exactly that, including the inline scripts.

根据您的设置,您可能希望从 www.cloudflare.com 查看该服务。他们当前的 beta 功能称为火箭装载机,正是这样做的,包括内联脚本。

It's a free service. try it out ;)

这是一项免费服务。试试看 ;)

Plus you get a free caching proxy on top :)

此外,您还可以获得一个免费的缓存代理:)

回答by Kevin

Instead of inline scripts, create inline functions. Then at the end of your javascript file, call the function if it exists.

创建内联函数而不是内联脚本。然后在 javascript 文件的末尾,调用该函数(如果存在)。

function inline_script() {.. code ..}

Inside your concatenated jquery+etc async javascript file:

在连接的 jquery+etc 异步 javascript 文件中:

if (typeof(inline_script) == 'function') inline_script()

You'll have to do some shuffling to make sure you only have one inline_script per page, or use some kind of caching to put them together if you call it more than once.

您必须进行一些改组以确保每页只有一个 inline_script,或者如果您多次调用它,则使用某种缓存将它们放在一起。

It's still a fun problem in the current age even though this question is old, async scripts = pretty awesome

尽管这个问题很老,但在当前时代它仍然是一个有趣的问题,异步脚本=非常棒

回答by skarE

Have a look at using headjs. It is a nice lightweight library that will do this all for you.

看看使用headjs。这是一个很好的轻量级库,可以为您完成这一切。