Julian Jelfs’ Blog

ScriptManager.CompositeScript issues

Posted in Uncategorized by julianjelfs on April 16, 2009

On the face of it the ScriptManager’s CompositeScript feature seems pretty useful. It allows you to combine multiple scripts together into a single script include at runtime. This is often a good idea since the cost in terms of latency of having a lot of individual script includes can be considerable (even if they are cached you may still have to pay the price of the 304 conditional GET). It can be a bad idea too of course because it can lead to larger overall download size and larger memory footprint of your browser cache. As always it’s a trade off.

Anyway, assume that you’ve decided that you want to do it and you choose to use the ScriptManager’s CompositeScript capability. The first problem I encountered is that there is a limit to the number of scripts that you can add to it. Though don’t expect anything as useful as a compile time error – no it will hit you at runtime with the following error:

The resource URL cannot be longer than 1024 characters. If using a CompositeScriptReference, reduce the number of ScriptReferences it contains, or combine them into a single static file and set the Path property to the location of it.

For me, this makes it pretty useless. But assuming that is not a problem, I then ran into another issue. I wanted to make my code conditional on build type such that I added a normal script reference to the script manager in a debug build to make development and debugging easier and added script references to the composite script when not in debug to get the benefits of the script combining when it matters. So I wrote code like the following:

public static void AddCompositeScript(Page page, string url)
{
    var sm = ScriptManager.GetCurrent(page);
    if (sm == null)
        throw new Exception(_messageManager.GetMessage(MessageKey.ScriptManagerUnfound));
#if DEBUG
    AddNormalScriptReference(sm, url);
#else
    sm.CompositeScript.Scripts.Add(new ScriptReference(url));
#endif
}

The problem seems to be with the page lifecycle. In a .Net page the OnLoad event fires before the OnPreRender event right? Correct. So if I register script A in the OnLoad event and script B in the OnPreRender event I know that script A will be included in the page before script B. This is the case if both script A and script B are registered as normal script references. However, if script B were registered as a Composite Script then it would end up being included on the page before script A in contrast to what the page lifecycle would have you expect. So it’s double bad because a) it seems to be wrong and b) it’s inconsistent.

My fiddler trace clearly show the composite script registered during pre-render being included in the page before other scripts included using normal script references during the the load phase.

So for me I think it’s more trouble than it’s worth. If you use content expiry on you static script files you can avoid the 304 conditional GET which basically means that once the user’s caches are primed, there is no down-side to having lots of script files. It is down to how much control you have over your user’s setup and how volatile your script files are. For me, script combining just doesn’t seem to be worth it.

Advertisements

5 Responses

Subscribe to comments with RSS.

  1. JustAsItSounds said, on July 8, 2009 at 7:45 am

    I’ve just found this problem and it is extremely annoying. I’m updating a control library that features several controls that require multiple (embedded) javascript resources. The controls are supposed to be stand-alone and as a result including a lot of controls causes undesirable file duplication.

    I started out using the ClientScriptManager which solved the problem of duplicate javascript includes but I ended up with 20 or so javascript includes. I then tried to use the ScriptManager.CompositeScript collection to compile these includes into a single, compressed include to optimise page-load times.

    The first problem I found was that ScriptManager didn’t recognise duplicate scriptreferences and added in the same files multiple times, throwing a run-time error.
    Fair enough, I thought, I’ll just manually check ScriptManager.CompositeScript.Scripts.Contains() before trying to add a reference. Didn’t make a difference.
    I finally resorted to using HttpContext.Current.Items collection to keep a string copy of each ScriptReference added to the ScriptManager.CompositeScript.Scripts collection and checking against that before adding.

    Then I get the *&^*&^ing “The resource URL cannot be longer than 1024 characters” error.

    %$# this. I’m going to roll my own cached handler. &^$%#ing waste of a day.

    • julianjelfs said, on July 8, 2009 at 12:43 pm

      Yes, I had much the same experience and ended up creating a mechanism of my own. It does seem like a very flawed concept if you can only use it if you know exactly how many scripts you are going to combine. I can’t imagine why they decided to live with this limitation when there are other solutions implemented with HttpHandlers that do not share this weakness.

      Sorry I have no real solution to offer ….

  2. Michael Freidgeim said, on June 26, 2011 at 1:21 am

    http://bellouti.wordpress.com/2008/09/14/combining-javascript-files-with-ajax-toolkit-library/ describes a workaround by using different ScriptManagerProxys

    • julianjelfs said, on June 26, 2011 at 8:12 am

      I’m sure that it works but it seems like a great deal of effort to go to, to fix something that just seems completely broken to me and is also so unnecessary. I’m happy to say that I have been ScriptManager free for months now with no regrets.

  3. […] I’ve read Combining Client Scripts into a Composite Script and wanted to use it. Then I’ve read Julian Jelfs concerns ScriptManager.CompositeScript issues […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: