Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving Ajax toolkit scripts to the bottom of the page

I'm currently working on improving one of our sites PageSpeed insights score, at the moment we're hovering around 90, we'd like to break into the mid 90's if possible.

One of the sticking points we have is that the Ajax toolkit script manager is generating its script at the top of the page, google flags this as a "should fix" issue and is complaining that the script is render blocking and should be moved to the bottom of the page or loaded asychronously or via the defer attribute.

I'm using the following to combine our scripts into one .js file to minimize requests:

<ajaxToolkit:ToolkitScriptManager ID="manScript" LoadScriptsBeforeUI="false" runat="server" EnableViewState="false" ScriptMode="Release">

    <CompositeScript ScriptMode="Release" Path="/CMSGlobalFiles/Js/combinedajax.min.js">
        <Scripts>
            <asp:ScriptReference Name="WebForms.js" Path="/CMSGlobalFiles/Js/aspnet/WebForms.js" Assembly="System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <asp:ScriptReference Name="MicrosoftAjax.js" Path="/CMSGlobalFiles/Js/aspnet/MicrosoftAjax.js"  />
            <asp:ScriptReference Name="MicrosoftAjaxWebForms.js" Path="/CMSGlobalFiles/Js/aspnet/MicrosoftAjaxWebForms.js" />
        </Scripts>
    </CompositeScript>

</ajaxToolkit:ToolkitScriptManager>

Is there a way to set either defer or async on the CompositeScript tag that gets output? Or any other way of moving this to the bottom of the page?

I've tried the following:

protected override void Render(HtmlTextWriter writer)
{
    StringWriter output = new StringWriter();
    base.Render(new HtmlTextWriter(output));

    string outputAsString = output.ToString();

    if(outputAsString.Contains("<script src=\"/CMSGlobalFiles/Js/combinedajax.min.js\" type=\"text/javascript\"></script>"))
    {
        outputAsString = outputAsString.Replace("<script src=\"/CMSGlobalFiles/Js/combinedajax.min.js\" type=\"text/javascript\"></script>", string.Empty);
    }

    writer.Write(outputAsString);
}

And then manually including a reference to the script at the bottom of the page:

<script type="text/javascript">
    function downloadJSAtOnload() {
        createScript("/CMSGlobalFiles/Js/combinedajax.min.js?v=1");
        createScript("//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js");
        createScript("/cmsglobalfiles/js/vendor/modernizr.js");
        createScript("/cmsglobalfiles/js/main.min.js");
        createScript("/cmsglobalfiles/js/vendor/wow.min.js");
    }

    function createScript(path) {
        var element = document.createElement("script");
        element.src = path;
        document.body.appendChild(element);
    }

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

This removes the generated composite script and creates a new one before the closing body tag, this brings our score up to 95 but I think this is loaded too late as we're getting a lot of console errors:

ReferenceError: Sys is not defined

WebForm_InitCallback is not defined

Which indicates the script manager is broken, is there a way to achieve this at all?

like image 685
DGibbs Avatar asked May 16 '16 08:05

DGibbs


1 Answers

this is a late answer in 2021. I see what you doing here. Easiest way is to preload the combinedajax.min.js in the head section.

You should no longer see problem with Google pagespeed. I am in similar shoes as you as I am using ACT (AJAX Control Toolkit) but since found alternatives to go around it.
like image 187
heesoo Avatar answered Nov 08 '22 01:11

heesoo