简体   繁体   English

推迟在asp.net MVC中加载javascript

[英]Defering the loading of javascript in asp.net MVC

I'm looking to optimise the way in which larger javascript files are loaded in my MVC project. 我正在寻找优化在MVC项目中加载较大的javascript文件的方式。 I'm already using bundling and minification but I would really like to only load a few of them AFTER the the HTML and CSS are loaded. 我已经在使用捆绑和缩小功能,但是我真的只想在HTML和CSS加载后再加载其中的一些。 I was looking at this kind of approach: 我正在研究这种方法:

https://varvy.com/pagespeed/defer-loading-javascript.html https://varvy.com/pagespeed/defer-loading-javascript.html

In this approach the script tags are injected into using javascript in the load/onload event after the body is loaded. 通过这种方法,在加载正文之后,在load / onload事件中使用javascript将脚本标签注入。 My problem is that I would like to use along side the bundling and minification offered by the framework and I haven't found a good way to do that. 我的问题是,我想同时使用框架提供的捆绑和缩小功能,但我还没有找到一种好的方法。

I'l just wondering if anybody has successfully used this approach with MVC projects and if there might already be a library (on Nuget or otherwise) to facilitate this. 我只是想知道是否有人在MVC项目中成功使用了这种方法,以及是否可能已经有一个库(在Nuget上或其他方式上)来简化此过程。

EDITED: Here is my current solution, but I'm not sure I like it. 编辑:这是我目前的解决方案,但我不确定我是否喜欢它。

Since the Bundling framework can return a single script tag or a list of them depending on whether you're running in debug or not we need to extract the source values for those tags. 由于捆绑框架可以根据您是否在调试中运行而返回单个脚本标签或它们的列表,因此我们需要提取这些标签的源值。 To do this I created a static helper. 为此,我创建了一个静态助手。

public static string ExtactFromScriptBundle(string aBundle)
    {
        List<string> returnValue = new List<string>();

        var jQueryString = Scripts.Render(aBundle).ToHtmlString();

        var reg = new Regex("\".*?\"");

        var matches = reg.Matches(jQueryString);
        foreach (var match in matches)
        {
            returnValue.Add(match.ToString().Replace("\"", ""));
        }

        return Json.Encode(returnValue);
    }

Than from _layout.cshtml you cound insert a block like the following right before the tag: 比起_layout.cshtml,您可以在标记之前插入一个类似于以下内容的代码块:

<script>
    function downloadJSAtOnload() {
     createScripElementsFromArray(@Html.Raw(ScriptHelper.ExtactFromScriptBundle("~/bundles/jquery")));
createScripElementsFromArray(@Html.Raw(ScriptHelper.ExtactFromScriptBundle("~/bundles/bootstrap")));
    }

    function createScripElementsFromArray(fileNameList) {
        var arrayLength = fileNameList.length;
        for (var i = 0; i < arrayLength; i++) {
            createScripElement(fileNameList[i]);
        }
    }

    function createScripElement(fileName) {
        var element = document.createElement("script");
        element.src = fileName;
        document.body.appendChild(element);
        console.log(fileName + " was loaded");
    }

    if (window.addEventListener)
        window.addEventListener("load", downloadJSAtOnload, false);
    else if (window.attachEvent)
        window.attachEvent("onload", downloadJSAtOnload);
    else window.onload = downloadJSAtOnload;
</script>

It's a bit a hack in my opinion since I'm rendering the bundles just to parse the output, but I guess I could also cache those outputs to further optimize the page rendering. 在我看来,这是一个小技巧,因为我只是为了分析输出而渲染捆绑包,但是我想我也可以缓存这些输出以进一步优化页面渲染。

By Occam's Razor , the best solution is to use the defer attribute ... 通过Occam的Razor ,最好的解决方案是使用defer属性...

<script src='myJavaScriptFile.js' defer></script>

It is well supported . 它得到很好的支持

If you want to use it in ASP.NET MVC, then you'll do this: 如果要在ASP.NET MVC中使用它,请执行以下操作:

Create a new Razor command like so: 创建一个新的Razor命令,如下所示:

public static class Scripts
{
    public static IHtmlString RenderDeferred(params string[] paths)
    {
        return Scripts.RenderFormat(@"<script src='{0}' defer></script>", paths);
    }
}

And then use it like this: 然后像这样使用它:

@Scripts.RenderDeferred("~/myBundle/myJavaScriptBundle")

One option is to use jquery to load external scripts. 一种选择是使用jquery加载外部脚本。 You'd have an initial dependency on jquery itself but jquery is very light weight. 您最初会对jquery本身有依赖性,但是jquery的重量很轻。

You'd then have: 然后,您将拥有:

$(document).ready(function(){

    //At this point, the HTML/CSS has already been loaded and rendered.

    //load external scripts
    $.getScript( "ajax/test.js", function( data, textStatus, jqxhr ) {
       console.log( data ); // Data returned
       console.log( textStatus ); // Success
       console.log( jqxhr.status ); // 200
       console.log( "Load was performed." );
    });

});

Jquery doc: https://api.jquery.com/jquery.getscript/ jQuery文档: https : //api.jquery.com/jquery.getscript/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM