Script reference profiler

ASP.NET Ajax 3.5 SP1 contains a new feature that enables the application developer to combine scripts in order to reduce the number of downloaded files. But in order to do that, the developer must have a way of discovering what scripts are being used in a page or application.

To make that easier, I've developed a small control that you can drop onto a page and that will render out the list of script references that are being used by the page. It is then easy to copy and paste that list into the CombinedScripts property of the script manager and combine all those references into one.

The control also renders two links that enable the developer to download the debug and release versions of the combined scripts. Those scripts can be downloaded, copied into the site and used with the Path property on CombinedScripts. This enables better server performance than the plain automatic combination that ScriptResource.axd performs, but it also means you need to re-generate that file every time any of the scripts change.

The project to build the control can be downloaded as part of the ASP.NET CodePlex project:
http://www.codeplex.com/aspnet/SourceControl/DirectoryView.aspx?SourcePath=%24%2faspnet%2fAJAX%2fFutures%2fScriptReferenceProfiler&changeSetId=7061

UPDATE: the component can also be downloaded in binary form from here:
http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=13356

23 Comments

  • Awesome control...

  • This is a good idea. I am curious where the combined script is stored and if the resulting JavaScript is minified (which would be really great). I assume that this feature could be used by a page that does not use ASP.NET Ajax as long as the developer puts a ScriptManager control and adds any application .js files that are normally included on the page, correct?

  • @J: The combined script is not exactly "stored". It is being generated by a handler dynamically (and output-cached). The JavaScript is not minified by the handler, but the infrastructure allows for a release and a debug version of each script, the release version being minified using one of the many tools available. You could use that with non ASP.NET Ajax frameworks if the scriptmanager didn't always include MicrosofAjax.js (which is something we're looking at relaxing in a future release).

  • Although it is a great idea and I'm sure it took a lot of effort to build the tool, I'm quite skeptical about the amount of performance gain obtained.

    How much do you really gain from this? Bandwidth and/or lag time?

  • @Andrei: you're absolutely right, the gains are most of the time quite modest, but it does add up on a high traffic site. Definitely not a feature that you need to use on each and every site, and definitely one you should use with caution.

  • Hi Bertrand,
    What about forcing the javascript's to load after the GUI, "loadscriptsbeforeui='false'", which has an even greater effect on what you perceive as performance, does this work with that? In 3.5 w/o SP1 it's not working completely well.

  • @Daniel: loadscriptsbeforeui should just work. If it doesn't, it's a bug and you can send me a repro using the contact form on this blog.

    @J: You can combine multiple physical script files using that feature, but we really don't recommend it as there is some server overhead related to file monitoring. What you're describing is much better handled by "building" your scripts at compile time instead of doing the combination at runtime. The feature really is for application developers who want to combine existing scripts from various components that they use in their application.
    The output caching expiration is set by the handler. The resulting files are cached at all levels, including client-side. The efficient client-side caching is made possible by the fact that the combined url varies every time one of the underlying files changed.

  • I've tried Telerik's SM that has this same feature and I have noticed quite a bit of improvement. The benefit is in the reduction of the chatter between the client and server. When you have more than 10 JavaScript includes and you reduce that to only a couple you will feel the difference.

    It is, however, debatable how useful it is. Yes, it will make the first access much faster, but if on page 1 you load scripts A through G, and on page 2 you want A through G and M, since it's all bundled, it will have to load the whole pack one more time. not just M. I guess it depends on your scenario.

    As far as compression: People please enable the built-in IIS (v 6 and 7) compression. It's there and it's quite good. You get the biggest bang for the buck just by enabling the compression (off by default in IIS6, not sure about IIS7).

  • @Peter: that's why you need to profile your application, not just a page. Which is why, in turn, we didn't make the feature all automatic because it would have made more harm than good in some cases.
    You're right about dynamic and static compression in IIS7, it's one of the most efficient ways to improve perf, but good perf is ultimately a combination of several things. I recommend reading "high performance web sites" by Steve Souders for a pretty comprehensive set of tricks along those lines.

  • Does this control only pick up certain script references? The reason I ask is that when using it it picked up all the Ajax Control Toolkit references and the AJAX references, but did not pick up others like scripts for the menu control, validators, and 3rd party infragistics references. They are being loaded with my page, but not being listed out by the control.

  • @Mike: it can only pick up script references that were registered with the script manager. Older ASP.NET scripts and third party scripts not using script manager will not get picked up (but they can't be combined either). We're considering making all references go through script manager if there is one on the page for v.next, which should solve that problem and make everything combinable.

  • @Mike: the toolkit manager can only combine resources that have been marked as combinable (which excludes MicrosoftAjax.js) and the combination is fully automatic, which in some cases results in worse performance across the site.

  • Hi Bertrand,
    Great Work ! (i have been using my custom scripts.ashx in several projects, but couldnt include the Control Toolkit js).
    Maybe you could add a minification to the script manager ? :-)

  • @Christoph: thanks. minification should really be done as part of the build process and not at runtime. It simply is too heavy.

  • Hi,

    When this thing will be integrated into visual studio . Can we expect this in Visual Studio 2010 ?

    Thanks

  • @MisterFantastic: we're currently not planning on integrating this into VS.

  • I have been using the CompositeScript tag and it works great in combining our scripts but it never caches on the client side. I have not been able to figure out why, but that is killing the performance benefit after the first page load.

    I have enabled caching by the scriptResourceHandler in the web config file, but that doesn't seem to have an effect.

    Has anyone else seen this problem or can give me a clue why it will never cache in the browser?

    Thanks!

  • @Lindsay: That sounds very strange. Can you send me a simple repro at bleroy at microsoft?

  • I have found that the debug/release links that the SRP provides on the page will not always provide the correct version of the script, if you've already clicked one of the links. For example, if you click the debug link you get the debug script, but if you then click the release link, you still get the debug script. I've found that refreshing the page before clicking either link ensures that you get the right script.

    Also, I've found that even if I provide a .debug.js and a .release.js version of my custom scripts, the combined script provided will always provide the release version of my script.

  • @Scott: I'll look at the first problem, but for the second one you might want to specify ScriptMode=inherit on the script reference if you want the system to understand a debug version of a static script file exists. foo.release.js should really be foo.js, also.

  • Hi again Bertrand,

    One last item to note:

    When I specify the debug version of my script should be used (via the ScriptManager's ScriptMode or the ScriptRefrence's ScriptMode), I will get that script version referenced in the rendered page, but the SRP will always list the release version on the screen. This is even true with the MS scripts.

    -Scott

  • Thanks so much! This worked brilliantly. I would never have thought to hook the ResolveScriptReference event to determine which scripts we needed.
    Great.

  • The link www.codeplex.com/.../DirectoryView.aspx is broken,

    but

    aspnet.codeplex.com/.../13356 is OK.

Comments have been disabled for this content.