Since you are here, you most likely know, but for others. wro4j (Web Resource Optimizer for Java) allows you (as name suggests) to optimize your web resources. Typically when you build (rich) web application you use several CSS/JS frameworks and develop additional CSS/JS of your own. And all of this needs to be downloaded to browser. That is not typically big problem for desktops with broad-band internet, but in era of mobile internet it is very helpful if you can bundle all of this to few HTTP requests that download everything needed together and in addition minimize and gzip the content (e.g. by removing your comments from JS).
wro4j can work in two modes – runtime and compile time. You can do all this magic compile time and just use results in your JAR/WAR. This has clear benefits (like no runtime dependency on wro4j, no runtime “compilation” etc) but also the setup was more complicated, you need to properly configure your IDE to “hot” recompile your resources as you are developing and you need to configure some features by yourself (e.g. caching/gzip). So for now I decided to use runtime setup with wro http filter.
wro4j itself does not have spring boot support, nor spring boot can autoconfigure it. I have found 3rd party library for that but I didn’t want to add additional maven repository just for that. Additionally I don’t like that is support only “pre-selected” configuration options (although the most used are there). Therefore I decided to configure it myself.
So first you need to add wro4j as dependency to your project (in my case maven):
<!-- wro4j --> <dependency> <groupId>ro.isdc.wro4j</groupId> <artifactId>wro4j-core</artifactId> <version>1.7.8</version> </dependency> <dependency> <groupId>ro.isdc.wro4j</groupId> <artifactId>wro4j-extensions</artifactId> <version>1.7.8</version> </dependency>
Then we need to configure wro4j filter in one of your @Configuration
classes.
@Bean FilterRegistrationBean webResourceOptimizer(Environment env) { FilterRegistrationBean fr = new FilterRegistrationBean(); ConfigurableWroFilter filter = new ConfigurableWroFilter(); filter.setProperties(buildWroProperties(env)); fr.setFilter(filter); fr.addUrlPatterns("/wro/*"); return fr; } private static final String[] OTHER_WRO_PROP = new String[] { ConfigurableProcessorsFactory.PARAM_PRE_PROCESSORS, ConfigurableProcessorsFactory.PARAM_POST_PROCESSORS }; private Properties buildWroProperties(Environment env) { Properties prop = new Properties(); for (ConfigConstants c : ConfigConstants.values()) { addProperty(env, prop, c.name()); } for (String name : OTHER_WRO_PROP) { addProperty(env, prop, name); } log.debug("Wro4J properties {}", prop); return prop; } private void addProperty(Environment env, Properties to, String name) { String value = env.getProperty("wro." + name); if (value != null) { to.put(name, value); } }
As you can see from code, it register filter to /wro/*
path and reads all properties from your application.properties
(or alternative) with “wro.” prefix. Unfortunately not all wro properties are part of ro.isdc.wro.config.jmx.ConfigConstants
, so if you need anything else, just extend OTHER_WRO_PROP
.
All what’s left is to “use” wro4j – create your wro.xml
in WEB-INF directory
<?xml version="1.0" encoding="UTF-8"?> <groups xmlns="http://www.isdc.ro/wro"> <group name="other"> <js>classpath:static/jquery/jquery-1.10.1.min.js</js> <js>classpath:static/timeago/jquery.timeago.1.4.1.js</js> <css>classpath:static/slider/slider.css</css> </group> </groups>
and setup your application.properties
as you want.
# wro4j config wro.preProcessors=cssUrlRewriting,cssImport,semicolonAppender,lessCss wro.postProcessors=cssVariables,cssMinJawr,jsMin # set to 1 second to check for resource changes wro.resourceWatcherUpdatePeriod = 0 wro.ignoreMissingResources = false
Enjoy.
Update: If you are not deploying .war file, you need to override where wro.xml
comes from. Check this sample project
4 Comments
Pete Storey
Thanks for this, a great help – except when I bootRun the project, I can’t work out how to get the wro.xml file into the WEB-INF directory, and I can’t find any help on the web for this?
I’ve tried in src/main/resources, src/main/resources/public/WEB-INF and so on and none seem to work 🙁
How did you manage it, or do you not bootRun?
Stanislav Miklik
I must (with shame :)) admit that I am packing application as WAR (see doc) although it is not very boot-way.
If I or someone solve this problem, I can add it to blog later on.
Mike Pridemore
Thanks for making the update for non-war applications. I’ve implemented it but it’s not finding the src/main/resources/wro.xml file. In fact, it’s not even writing out the log message at the beginning of Wro4jCustomXmlModelManagerFactory.newModelFactory() so it seems like it’s not loading. I’m banging my head to figure this out but not having any luck. Any ideas?
Stanislav Miklik
Does sample project work for you? Wro4jCustomXmlModelManagerFactory is registered during filter registration at startup but Wro4J uses lazy initialization and creates the model factory only with first request.