Showing posts with label minification. Show all posts
Showing posts with label minification. Show all posts

Trimming white space and entra lines from the markup generated by WebSphere Application Serve

If you look at the HTML markup generated for IBM's default page you will notice that it has lot of white spaces and though they increase size of the response they are not required to display the page properly. If you set the com.ibm.wsspi.jsp.usecdatatrim custom property to true for your JSP engine, all of the white space and extra lines in the generated Java code are stripped out.

Take a look at the page which has two portlets and default IBM theme,



The page that gets generated is 64kb's in size and if you look at the view source you can see all the white spaces.

Now set com.ibm.wsspi.jsp.usecdatatrim equal to true as Web Container Custom property like this



Restart the server and try accessing the same page, you will notice that the size of the markup is reduced to 56.4 kb (Which is saving of close to 15 %) like this



The saving size could be much larger if your page is more complex.

Ant Task to compress JavaScript and CSS using YUICompressor

In the Ant task for combining multiple JavaScript files into one and minifying them using Dojo Shrinksafe entry i built a sample ant task that can be used to combine and minify JavaScript using Dojo ShrinkSafe.

But what if you want to use the YUI Compressor, or you want to combine and minify css, so i built this task for that


<target name="minify" >
<antcall target="minifyjs" />
<antcall target="minifycss" />
</target>
<target name="minifyjs" >
<mkdir dir="build/WebContent/js" />
<concat destfile="build/WebContent/js/combined.js">
<fileset dir="WebContent/js" includes="*.js" />
</concat>
<java fork="true" jar="${yuicompressor.lib.dir}" dir="build/WebContent/js"
output="build/WebContent/js/combined.min.js">
<arg value="combined.js" />
</java>
</target>

<target name="minifycss" >
<mkdir dir="build/WebContent/css" />
<concat destfile="build/WebContent/css/combined.css">
<fileset dir="WebContent/css" includes="*.css" />
</concat>
<java fork="true" jar="${yuicompressor.lib.dir}" dir="build/WebContent/css"
output="build/WebContent/css/combined.min.css">
<arg value="combined.css" />
</java>
</target>



The minify task is broken into two parts one is minifyjs which combines and minfies all the JavaScript files in /js folder and the minifycss which combines and minifies all the css files in /css folder.

Compressing the JavaScript and CSS files on the fly using YUI COmpressor

I was trying to build a Servlet and Filter which can be used to minify JavaScript and CSS on the fly using YUI COmpressor. But i ran into this exception. When i was searching for solution to this problem i found WebUtils project which has
following components which can use easily used in J2EE webapp.


  • JSCSSMergeServlet - to merge multiple JS or CSS and serve them in one HTTP request.

  • YUIMinFilter - to compress JS or CSS resources on the fly using YUI compressor.

  • YuiMinTag - Custom tag to compress inline JS and CSS code using YUI compressor in JSPs.





[8/9/10 11:46:59:322 PDT] 0000008d ServletWrappe E SRVE0068E: Uncaught exception thrown in one of the service methods of the servlet: YUICompressorDemoServlet. Exception thrown : java.lang.StringIndexOutOfBoundsException
at java.lang.String.substring(String.java:1088)
at com.yahoo.platform.yui.compressor.JavaScriptCompressor.printSourceString(JavaScriptCompressor.java:268)
at com.yahoo.platform.yui.compressor.JavaScriptCompressor.parse(JavaScriptCompressor.java:333)
at com.yahoo.platform.yui.compressor.JavaScriptCompressor.(JavaScriptCompressor.java:536)
at com.webspherenotes.performance.minfy.YUICompressorDemoServlet.doGet(Unknown Source)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:743)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1146)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:592)
at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:524)
at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3517)
at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:269)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:818)
at com.ibm.ws.wswebcontainer.WebContainer.handleRequest(WebContainer.java:1478)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:125)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:458)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:387)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:267)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:136)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:196)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:751)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:881)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1497)

Ant task for combining multiple JavaScript files into one and minifying them using Dojo Shrinksafe

In the Combining and minifying multiple JavaScript files into one on the fly, entry i built a Servlet that can be used to combine multiple JavaScript files into one. But its always better to combine multiple JavaScript into one during the build time instead of run time.

So this is the Ant task that you can add to your build file which can do the combining and minfiying for you


<target name="shrinksafe" >
<concat destfile="WebContent/js/combined.js">
<fileset dir="WebContent/js" includes="*.js" />
</concat>
<java fork="true" jar="${shrinksafe.lib.dir}/shrinksafe.jar"
dir="build/WebContent/js"
output="WebContent/js/combined.min.js">
<classpath>
<pathelement location="${shrinksafe.lib.dir}/js.jar"/>
</classpath>
<arg value="combined.js" />
</java>
</target>


The task can be broken into two pieces first you will have to combine multiple JavaScript files into one and i am using concat element for it, what it does is find all the JavaScript files inside WebContent/js and combine them together into combined.js which will be saved in WebContent/js folder.

Once the combined JavaScript file is ready i am executing the shrinksafe.jar, passing it the combined.js as argument and the output of this command would be saved into combined.min.js. Hereafter whenever you want to include the combined javascript include combined.min.js on your page.

Combining and minifying multiple javascript files into one on the fly

In the On the fly JavaScript minification using Dojo ShrinkSafe entry i built a simple ServletFilter that can be used to minify JavaScript files on the fly.

After i published that entry i got email from a reader that how can we combine and minify multiple JavaScript file into one so i built this filter which can be used to minfiy multiple JavaScript files into one and then minify the resultant file using Dojo Shrinksafe


package com.webspherenotes.performance.minfy;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.dojotoolkit.shrinksafe.Compressor;

/**
* Servlet implementation class ShrinkSafeAntDemoServlet
*/
public class ShrinkSafeAntDemoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
* Default constructor.
*/
public ShrinkSafeAntDemoServlet() {
// TODO Auto-generated constructor stub
}

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/javascript");
ArrayList fileList = getFileList(request.getParameter("fileList"));
String combinedFile = getCombinedFile(fileList);
System.out.println("Combined JavaScript " + combinedFile);
String outputJavaScript = Compressor.compressScript(combinedFile, 0, 1, "all");
response.getWriter().println(outputJavaScript);
}

private ArrayList getFileList(String fileListStr){
StringTokenizer st = new StringTokenizer(fileListStr, ",");
ArrayList fileList = new ArrayList();
while(st.hasMoreElements()){
fileList.add((String)st.nextElement());
}
return fileList;
}

private String getCombinedFile(ArrayList fileList) throws IOException{
StringBuffer combinedJavaScript = new StringBuffer();
for(int i = 0 ; i < fileList.size(); i++){
String fileName = (String)fileList.get(i);
System.out.println("Read the file " + fileName);
BufferedReader br = new BufferedReader( new InputStreamReader(
getServletContext().getResourceAsStream(fileName)));
String line = null;
while((line =br.readLine()) != null){
combinedJavaScript.append(line);
combinedJavaScript.append("\n");
}
}
return combinedJavaScript.toString();
}
}


You can call this servlet passing it list of JavaScript files that you want to combine as argument, i am assuming that those files are part of the same web application as that of the servlet. Assume that you have test.js, test1.js and test2.js files in your web application and instead of including each one of them separately on a page you want to include all 3 of them together like this.


< script
src='/shrinksafe/ShrinkSafeAntDemoServlet?fileList=/js/test.js,/js/test1.js,/js/test2.js' >


The ShrinkSafeAntDemoServlet first reads value of fileList parameter and parse it to find out the number of files that you want to combine, then getCombinedFile() method takes list of JavaScript files as argument and reads and combines them into a String. Once the String is read it passes control to Compressor.compressScript() method of Dojo compressor to minify the mulitple JavaScript files

YUI Compressor

The YUI Compressor is another tool similar to Dojo ShrinkSafe, that we can use to minify JavaScript. It can also be used to minify CSS files.


If you want to use YUI COmpressor first you should download it from here. Then you use it using command line tool.



  • You can use following syntax to compress test.js into test.min.js

    java -jar yuicompressor-***.jar -o test.min.js test.js

    It seems that YUI Compressor does nto support combining multiple files into one, instead you will have to use either cat command on linux or copy command on windows to combine multiple files into one and then use YUICompressor to minify the resultant file

  • You can use the YUI COmpressor to compress the CSS files too, it depends on the file extension to figure out if its .js or .css file and takes care to minify it accordingly

    java -jar yuicompressor-***.jar -o test.min.css test.css


    But if you want you can also specify the the --type command to specify the type of file you want to compress, so the syntax for compressing CSS file would be like this

    java -jar yuicompressor-***.jar --type css -o test.min.css test.css




Take a look at YUI compressor help page for details on the command line option