简体   繁体   中英

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. 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. I was looking at this kind of approach:

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

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:

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

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

Create a new Razor command like so:

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. You'd have an initial dependency on jquery itself but jquery is very light weight.

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/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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