Sunday, March 11, 2012

JSP/Servlet: Use Jawr to reduce page load times.

Introduction

From official site:
Jawr is a tunable packaging solution for Javascript and CSS which allows for rapid development of resources in separate module files. Developers can work with a large set of split javascript files in development mode, then Jawr bundles all together into one or several files in a configurable way.
By using a tag library, Jawr allows you to use the same, unchanged pages for development and production. Jawr also minifies and compresses the files, resulting in reduced page load times.

Getting started

Get required jars:
download Jawr 3.3.3:
http://java.net/projects/jawr/downloads/directory/release
get log4j:
http://mvnrepository.com/artifact/log4j/log4j/1.2.16

Then put them into WEB-INF/lib

Create Javascript/CSS files:
The project architecture and Javascript/CSS files are as below



Config Javascript/CSS Servlet in WEB-INF/web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    <servlet>
        <servlet-name>JavascriptServlet</servlet-name>
        <servlet-class>net.jawr.web.servlet.JawrServlet</servlet-class>

        <!-- Location in classpath of the config file
            it should be a path under classpath,
            the value is /test/jawr.properties here because
            we put the file "jawr.properties" under /src/test and
            it will be moved to classpath/test/ after compiled -->
        <init-param>
            <param-name>configLocation</param-name>
            <param-value>/test/jawr.properties</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet>
        <servlet-name>CSSServlet</servlet-name>
        <servlet-class>net.jawr.web.servlet.JawrServlet</servlet-class>

        <!-- Location in classpath of the config file
            it should be a path under classpath,
            the value is /test/jawr.properties here because
            we put the file "jawr.properties" under /src/test and
            it will be moved to classpath/test/ after compiled -->
        <init-param>
            <param-name>configLocation</param-name>
            <param-value>/test/jawr.properties</param-value>
        </init-param>
        <init-param>
            <param-name>type</param-name>
            <param-value>css</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- the url-pattern can be any value, we use *.jsbundle / *.cssbundle here -->
    <servlet-mapping>
        <servlet-name>JavascriptServlet</servlet-name>
        <url-pattern>*.jsbundle</url-pattern>
    </servlet-mapping> 

    <servlet-mapping>
        <servlet-name>CSSServlet</servlet-name>
        <url-pattern>*.cssbundle</url-pattern>
    </servlet-mapping>
</web-app>

Config jawr in src/test/jawr.properties:

# Common properties
jawr.debug.on=false
jawr.gzip.on=true
jawr.gzip.ie6.on=false
jawr.charset.name=UTF-8

# Javascript properties and mappings
jawr.js.bundle.basedir=/js

# All files within /js/bundleOne will be together in a bundle
# mappings to /bundles/jsbundle_one.jsbundle.
# All files within /js/bundleTwo will be together in a bundle
# mappings to /bundles/jsbundle_two.jsbundle.
# the jsbundleOne / jsbundleTwo in the mapping key
# can be any value  
jawr.js.bundle.jsbundleOne.id=/bundles/jsbundle_one.jsbundle
jawr.js.bundle.jsbundleOne.mappings=/js/bundleOne/**
jawr.js.bundle.jsbundleTwo.id=/bundles/jsbundle_two.jsbundle
jawr.js.bundle.jsbundleTwo.mappings=/js/bundleTwo/**

# CSS properties and mappings
jawr.css.bundle.basedir=/css

jawr.css.bundle.cssbundle.id=/bundles/cssbundle.cssbundle
jawr.css.bundle.cssbundle.mappings=/css/**

########## another way ##########
## note: singlebundle currently only works with
##       url-pttern ends with .css,
##       have to modify the web.xml and
##       test.jsp before use this way
## CSS properties and mappings
# jawr.css.bundle.basedir=/css
#
## CSS files will be all bundled together automatically
# jawr.css.factory.use.singlebundle=true
# jawr.css.factory.singlebundle.bundlename=/bundles/cssbundle.css

Note singlebundle currently only works with the url-pattern endswith .css for css files,
please refer jawr tracker:
http://java.net/jira/browse/JAWR-228

test file index.jsp (without Jawr)

<%@ page isErrorPage="true" language="java"
    contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page isELIgnored ="false" %>
<html>
    <head>
        <meta http-equiv="Content-Type" 
            content="text/html; charset=UTF-8"/>
        <title>Normal - without JAWR</title>
        <link href="css/aaa.css" rel="stylesheet" type="text/css">
        <link href="css/bbb.css" rel="stylesheet" type="text/css">
        <link href="css/ccc.css" rel="stylesheet" type="text/css">
        <link href="css/ddd.css" rel="stylesheet" type="text/css">
        <link href="css/eee.css" rel="stylesheet" type="text/css">
        <script type="text/javascript" src="js/bundleOne/aaa.js"></script>
        <script type="text/javascript" src="js/bundleOne/bbb.js"></script>
        <script type="text/javascript" src="js/bundleOne/ccc.js"></script>
        <script type="text/javascript" src="js/bundleTwo/ddd.js"></script>
        <script type="text/javascript" src="js/bundleTwo/eee.js"></script>
        <script type="text/javascript">
            onload = function () {
                funcA();
                funcB();
                funcC();
                funcD();
                funcE();
            }
        </script>
    </head>
    <body>
        <div class="class_a">
            js file <span id="funcA"></span> loaded
        </div>
        <div class="class_b">
            js file <span id="funcB"></span> loaded
        </div>
        <div class="class_c">
            js file <span id="funcC"></span> loaded
        </div>
        <div class="class_d">
            js file <span id="funcD"></span> loaded
        </div>
        <div class="class_e">
            js file <span id="funcE"></span> loaded
        </div>
    </body>
</html>

test file test.jsp (use Jawr)

<%@ page isErrorPage="true" language="java"
    contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page isELIgnored ="false" %>
<%@ taglib uri="http://jawr.net/tags" prefix="jwr" %>
<html>
    <head>
        <meta http-equiv="Content-Type" 
            content="text/html; charset=UTF-8"/>
        <title>Normal - without JAWR</title>
        <jwr:style src="/bundles/cssbundle.cssbundle" />
        <jwr:script src="/bundles/jsbundle_one.jsbundle"/>
        <jwr:script src="/bundles/jsbundle_two.jsbundle"/>
        <script type="text/javascript">
            onload = function () {
                funcA();
                funcB();
                funcC();
                funcD();
                funcE();
            }
        </script>
    </head>
    <body>
        <div class="class_a">
            js file <span id="funcA"></span> loaded
        </div>
        <div class="class_b">
            js file <span id="funcB"></span> loaded
        </div>
        <div class="class_c">
            js file <span id="funcC"></span> loaded
        </div>
        <div class="class_d">
            js file <span id="funcD"></span> loaded
        </div>
        <div class="class_e">
            js file <span id="funcE"></span> loaded
        </div>
    </body>
</html>

Test Result:

In short, it is about 2 times faster.

The result that load index.jsp  (without Jawr) 3 times as below:







The result that load test.jsp (with Jawr) 3 times as below:






Download:
The full project at github
https://github.com/benbai123/JSP_Servlet_Practice/tree/master/Practice/Tools/JAWR

References:
http://jawr.java.net/
http://jawr.java.net/tutorials/quickstart.html

2 comments:

  1. when i use the jawr in my project ,the function created with ajax did not work ,i don't understand the cause!!!!

    ReplyDelete
    Replies
    1. Hmm... didn't try it with ajax, sounds interesting.

      Delete