NOTE: I am excited to have Rick Kiessig as our guest blogger. Rick worked with Myspace, MSN, eBay, and Silicon Valley’s MTC to mention a few. His recent work is a book Ultra-Fast ASP.NET which anyone who’s serious about performance should buy once it is out this month. Rick shares with us a little trick about how to generate dynamic JS so it can be then cached to boost performance.
When you get down to it, ASP.NET is really just a fancy way of generating text in response to an HTTP request. Although that text is normally HTML, it doesn’t have to be. You can also use it to create JavaScript, CSS or even robots.txt.
As a practical application, think about how you would localize text that resides in a script file. One solution might be to detect the desired language and redirect to an appropriate, localized version of the script file. Alternatively, you might include text for all supported languages in the same script file, and choose between them on the client. However, a better way is use ASP.NET to generate a dynamic version of the script file. The result helps performance by preventing a redirect, eases maintenance by allowing you to partition localized strings in the same way that you do for the rest of your application, and minimizes the size of the downloaded file.
After defining your localization strings in a global resource file, as you would for a web page, the next step is to create an .aspx file and set StyleSheetTheme to be an empty string. If you don’t do that, then the runtime will insist on a <head> section in the .aspx file:
<%@ Page Language="C#" AutoEventWireup="false" CodeFile="script.aspx.cs"
Inherits="scripts_script" EnableViewState="false" StyleSheetTheme="" %>
<%@ Import Namespace="Resources" %>
<%@ OutputCache Duration="259200" VaryByCustom="language" VaryByParam="None" %>
function test() {
testinfo.innerHTML = "<%= Resource.Email %>";
}
Import the Resources namespace, to make it easier to reference. You can also enable output caching here, so that the result will be cached on the client and at the server. Using VaryByCustom will allow you to vary the cache output based on the user’s language choice, through whichever mechanism is appropriate for the rest of your application (you will also need a GetVaryByCustomString() method, which I haven’t shown here).
The JavaScript itself then follows. In this case, you have a function that sets the innerHTML property of an element on the page to the value of a string that you obtain from the resource file. Of course, you can do any of the same kinds of server-side operations here that you would do for a web page, including the use of custom user controls, browser-specific code, and so on.
Here’s the code-behind:
using System;
public partial class scripts_script
{
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.Response.ContentType = "application/x-javascript";
}
}
The only thing you need to do is to set the MIME type of the response to indicate that it’s JavaScript.
One complication that can arise with this approach is that although it supports different languages for different users, it doesn’t allow a user to switch from one language to another. The brute-force solution is not to allow the script file to be cacheable. A better way, that retains cacheability, is to have dynamic code on the client that selects a different version of the script file based on the language the user selects. The script can figure that out based on a cookie. The ultimately requested URL might include a query string that specifies the language, or you could use URL rewriting on the server to direct URLs without query strings to the same .aspx file. Using URL rewriting and avoiding a query string can allow the result to be remain cacheable by the high-performance http.sys cache.
Richard Kiessig
Author of Ultra-Fast ASP.NET (published by Apress, Oct 2009)
Visit my new site at http://www.12titans.net/ (available at the end of Oct 2009)