Moving Ajax toolkit scripts to the bottom of the page
Asked Answered
E

2

9

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?

Evident answered 16/5, 2016 at 8:36 Comment(2)
What version of ACT do you use? Did you try to upgrade to the latest one and use Bundling?Medrano
@MikhailTymchuk I am currently using bundling as you can see but the issue is that the generated bundle script appears at the top of the page and is flagged as render blockingEvident
M
1

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.
Monumentalize answered 13/8, 2021 at 1:55 Comment(0)
H
0

Im using ajax control toolkit version 15.1.4.0, where you use ScriptManager instead of ToolkitScriptManager but there you can just set LoadScriptsBeforeUI="False" and it renders just before </form>.

Hachmann answered 2/8, 2016 at 7:23 Comment(3)
it moves most of the scripts to the bottom but in my case it caused some issues with other inline scripts so this might not be foolproof but you can atleast try it and see if it works in your caseHachmann
I'm afraid i'm not using ScriptManager, my example shows that I'm using <ajaxToolkit:ToolkitScriptManager /> and I have already set LoadScriptsBeforeUI too.Evident
@Evident sorry didn't notice LoadScriptsBeforeUI in your code.Hachmann

© 2022 - 2024 — McMap. All rights reserved.