On the fly JavaScript minification using Dojo ShrinkSafe

The Dojo ShrinkSafe is a tool that you can use to minify JavaScript, it can reduce size of JavaScript by close to 1/3 rd or more. You can call ShrinkSafe through commandline, or through Ant as part of your web applications build process. I wanted to see if i can call ShrinkSafe Java API to minify JavaScript.

I built ShrinkSafeFilter which will be part of my .war file and then i applied it to JavaScript URLs and what the ShrinkSafeFilter will do is it will collect the JavaScript file response into String minify it using ShrinkSafe API and return the minifed version to the browser, you can download the sample code from here

My Web application has index.html that includes three JavaScript files which are inside the /WebContent/js folder, this is the screen shot of how the test.js file looks like in the firebug




These are the steps that i had to follow to create ShrinkSafe Filter

  • First i had to create a ShrinkSafeFilter like this


    package com.webspherenotes.performance.minfy;

    import java.io.IOException;

    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.dojotoolkit.shrinksafe.Compressor;

    public class ShrinkSafeFilter implements Filter{


    public void destroy() {
    System.out.println("Entering ShrinkSafeFilter.destroy()");
    System.out.println("Exiting ShrinkSafeFilter.destroy()");
    }

    public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain filterChain) throws IOException, ServletException {
    try {
    System.out.println("Entering ShrinkSafeFilter.doFilter()");

    System.out.println("Received request for " + ((HttpServletRequest)request).getPathInfo());
    SSHttpServletResponseWrapper responseWrapper = new SSHttpServletResponseWrapper((HttpServletResponse)response);
    filterChain.doFilter(request, responseWrapper);
    responseWrapper.finishResponse(response.getWriter());
    System.out.println("Exiting ShrinkSafeFilter.doFilter()");
    } catch (Throwable e) {
    e.printStackTrace(System.out);
    }
    }

    public void init(FilterConfig arg0) throws ServletException {
    System.out.println("Entering ShrinkSafeFilter.init()");
    System.out.println("Exiting ShrinkSafeFilter.init()");
    }

    }

    In the doFilter() method of ShrinkSafeFilter i am wrapping the HttpServletResponse object into the SSHttpServletResponseWrapper method, and then forwarding control to application server for letting it written the static JavaScript file

  • This is how my SSHttpServletResponseWrapper.java looks like
    package com.webspherenotes.performance.minfy;

    import java.io.IOException;
    import java.io.PrintWriter;

    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpServletResponseWrapper;

    import org.dojotoolkit.shrinksafe.Compressor;

    public class SSHttpServletResponseWrapper extends HttpServletResponseWrapper{

    StringOutputStream stringOutputStream;

    public SSHttpServletResponseWrapper(HttpServletResponse response) {
    super(response);
    }


    public ServletOutputStream getOutputStream() throws IOException {
    stringOutputStream = new StringOutputStream();
    return stringOutputStream;
    }

    public void finishResponse(PrintWriter writer){
    String inputJavaScript = stringOutputStream.getString();
    long beginTime = System.currentTimeMillis();
    String outputJavaScript = Compressor.compressScript(inputJavaScript, 0, 1, "all");
    System.out.println("Time took to compress " +( System.currentTimeMillis() -beginTime));
    writer.println(outputJavaScript);

    }

    }

    In the getOutputStream() method i am returning a custom ServletOutputStream object that will be used for collecting the actual response into String. Then inside the finishResponse() method i am taking the actual JavaScript output returned by application server into String and calling the Compressor.compressScript(inputJavaScript, 0, 1, "all") method of ShrinkSafe to minify it.

  • THis is how my StringOutputStream class looks like

    package com.webspherenotes.performance.minfy;

    import java.io.ByteArrayOutputStream;
    import java.io.IOException;

    import javax.servlet.ServletOutputStream;

    class StringOutputStream extends ServletOutputStream {

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

    public void write(byte[] b, int offset, int length) throws IOException {
    byteArrayOutputStream.write(b, offset, length);
    }

    public void write(byte[] b) throws IOException {
    byteArrayOutputStream.write(b);
    }

    public void write(int b) throws IOException {
    byteArrayOutputStream.write(b);
    }

    public String getString() {

    return new String(byteArrayOutputStream.toByteArray());
    }

    public void close() throws IOException {
    byteArrayOutputStream.close();
    }

    public void flush() throws IOException {
    byteArrayOutputStream.flush();
    }

    }

    This is simple ServletOutputStream class that collects the response in string



This is how the firebug output looks like after i applied the ShrinkSafeFilter to it, did you notice the shinksafe has removed comments from the test.js and also the indentation.

4 comments:

buyi wen said...

i find a free online service to compress js and minify css, so it will reduce the size of web page.

srjwebsolutions said...

We are leading responsive website designing and development company in Noida.
We are offering mobile friendly responsive website designing, website development, e-commerce website, seo service and sem services in Noida.

Responsive Website Designing Company in Noida
Website Designing Company in Noida
SEO Services in Noida
SMO Services in Noida

Vikas Chaudhary said...

Battery Mantra is Authorized exide car battery dealer in Noida and Greater Noida. We are providing our service in Indirapuram, Delhi, Ashok Nagar.

Exide Battery Dealer in Noida
Battery Dealer in Noida
Authorized Battery Dealer in Noida
Car Battery Dealer in Noida
Car Battery Dealer
Exide Battery Dealer

EG MEDI said...

Egmedi.com is online medical store pharmacy in laxmi nagar Delhi. You can Order prescription/OTC medicines online.
Cash on Delivery available. Free Home Delivery


Online Pharmacy in Delhi
Buy Online medicine in Delhi
Online Pharmacy in laxmi nagar
Buy Online medicine in laxmi nagar
Onine Medical Store in Delhi
Online Medical store in laxmi nagar
Online medicine store in delhi
online medicine store in laxmi nagar
Purchase Medicine Online
Online Pharmacy India
Online Medical Store