Caching Dynamically Generated Scripts

If static JavaScript or CSS files are served from the application server, we take it for granted that they are going to be cached by the browsers. However, dynamically generated content (Javascript and CSS in particular) could also be cached as if it is static and sent from the server only when it is changed. Nevertheless, application servers provide no support for this at all. So, the responsibility rests on the shoulders of the server-side code which generates dynamic content.

I looked all over the Internet but was unable to find a solution, so I wrote my own code. It's written for a Java Servlet but the same logic can be applied to other languages too. The servlet below sends a piece of JavaScript to the client that it builds dynamically and adds the necessary headers to the response so that the browser can cache it.

Here's the code that gets the job done:

public class TestServlet extends HttpServlet {
    private static final String CONTENT_TYPE = "application/x-javascript";

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }

    public void doGet(HttpServletRequest request, 
                      HttpServletResponse response) throws ServletException, IOException {
        
        Calendar c1 = Calendar.getInstance();
        c1.clear();
        c1.set(2011,2,22,13,12);
        long lastModifiedDate = c1.getTimeInMillis();
        
        response.setContentType(CONTENT_TYPE);
        response.addDateHeader("Last-Modified",lastModifiedDate);
        
        PrintWriter out = response.getWriter();
    
        long lastFetchedDate = request.getDateHeader("If-Modified-Since");
        boolean notModified = false;
        if (lastFetchedDate>-1){
            if (lastModifiedDate<=lastFetchedDate){
                response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                notModified = true;
            }
        }
        if (!notModified){
            System.out.println("test");
            out.println("var test = {};");
            out.println("test['a']='b';");
            out.println("alert(test['a']);");
        }
        
    }

    public void doPost(HttpServletRequest request, 
                       HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
} 
 
To keep the example simple, I used a static date for the last modified date.

Here is how you can include this servlet in an html document as a javascript file:

<html>
    <head>
    <script type="text/javascript" src="http://localhost/test/testservlet"></script>
    </head>
    <body>
    </body>
</html>


When you run this from an application server, the first time you access the page you will see the message "test" in application server console, meaning that the servlet did the necessary work and generated the JavaScript code. The next time you access the page, the JavaScript will already be cached by the browser. Therefore, even the alert still pops up when the page is accessed, you will not the see message "test" in the server console. Since the dynamically created JavaScript is already cached in the browser and the headers were set up correctly, the server did not bother to generate the code all over again and responded much faster just like it would if the JavaScript was actually in a static file. 

M. Serdar Bi├žer

Comments

Popular posts from this blog

Powerful Free Webinar Network for Oracle Developers

PL/SQL Developers! Formspider 1.9 is Out