Html minification using AEM 6.1 | Community
Skip to main content
susheel
May 8, 2018

Html minification using AEM 6.1

  • May 8, 2018
  • 2 replies
  • 11644 views

There might be requirements to minify html but we dont have anything in AEM OOTB.

I have written a custom filter to minify the html and this is how the filter config looks like:

The below is the rough code for html compression.

HtmlCompressionFilter.java

import java.io.IOException;

import java.util.Map;

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.HttpServletResponse;

import org.apache.felix.scr.annotations.Activate;

import org.apache.felix.scr.annotations.Deactivate;

import org.apache.felix.scr.annotations.Property;

import org.apache.felix.scr.annotations.PropertyUnbounded;

import org.apache.felix.scr.annotations.sling.SlingFilter;

import org.apache.felix.scr.annotations.sling.SlingFilterScope;

import org.apache.jackrabbit.oak.commons.PropertiesUtil;

import org.apache.sling.api.SlingHttpServletRequest;

import org.apache.sling.api.SlingHttpServletResponse;

import org.apache.sling.api.resource.Resource;

import org.osgi.service.component.ComponentContext;

import com.capella.website.common.CommonLogger;

import com.googlecode.htmlcompressor.compressor.HtmlCompressor;

/**

* This Class HtmlCompressionFilter will have two options in config to enable

* and disable html compression. We can also provide the paths where we need to

* add compression.

*/

@SlingFilter(label = "HTML Compression Filter", description = "HTML Compression Filter", metatype = true, order = 0, scope = SlingFilterScope.REQUEST)

public class HtmlCompressionFilter implements Filter {

private HtmlCompressor compressor;

@Property(label = "Enable html compression", boolValue = false, description = "Please Check the property to enable html compression")

public static final String HTML_COMPRESSION_ENABLED = "html.compression.enabled";

@Property(value = {

"/content/project/en" }, unbounded = PropertyUnbounded.ARRAY, label = "Compress html paths", cardinality = 50, description = "Please enter the paths where you need to compress the html")

private static final String HTML_COMPRESSION_PATHS = "html.compression.paths";

private boolean isHtmlCompressionEnabled;

private String[] htmlCompressionPaths;

@Override

public void init(FilterConfig filterConfig) throws ServletException {

compressor = new HtmlCompressor();

compressor.setCompressJavaScript(true);

    compressor.setCompressCss(true);

}

@Override

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

throws IOException, ServletException {

if (!(request instanceof SlingHttpServletRequest) || !(response instanceof SlingHttpServletResponse)) {

chain.doFilter(request, response);

return;

}

final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;

final Resource resource = slingRequest.getResource();

String requestPath = resource.getPath() + ".html";

if (isHtmlCompressionEnabled && startsWithInArr(htmlCompressionPaths, requestPath)) {

CharResponseWrapper responseWrapper = new CharResponseWrapper((HttpServletResponse) response);

chain.doFilter(request, responseWrapper);

String servletResponse = responseWrapper.toString();

response.getWriter().write(compressor.compress(servletResponse));

} else {

chain.doFilter(request, response);

}

}

public boolean startsWithInArr(String[] htmlCompressionPaths, String requestPath) {

boolean flag = false;

for (int i = 0; i < htmlCompressionPaths.length; i++) {

if (requestPath.startsWith(htmlCompressionPaths[i])) {

flag = true;

break;

}

}

return flag;

}

@Override

public void destroy() {

}

@Activate

protected void activate(final Map<String, String> properties) {

this.isHtmlCompressionEnabled = PropertiesUtil.toBoolean(properties.get(HTML_COMPRESSION_ENABLED), false);

this.htmlCompressionPaths = PropertiesUtil.toStringArray(properties.get(HTML_COMPRESSION_PATHS));

}

@Deactivate

protected void deactivate(ComponentContext componentContext) {

}

}

CharResponseWrapper.java

import java.io.CharArrayWriter;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpServletResponseWrapper;

public class CharResponseWrapper extends HttpServletResponseWrapper {

  private final CharArrayWriter output;

  @Override

  public String toString() {

    return output.toString();

  }

  public CharResponseWrapper(HttpServletResponse response) {

    super(response);

    output = new CharArrayWriter();

  }

  @Override

  public PrintWriter getWriter() {

    return new PrintWriter(output);

  }

}

Dependencies required:

<dependency>

<groupId>com.googlecode.htmlcompressor</groupId>

<artifactId>htmlcompressor</artifactId>

<version>1.4</version>

</dependency>

<dependency>

<groupId>com.yahoo.platform.yui</groupId>

<artifactId>yuicompressor</artifactId>

<version>2.4.6</version>

</dependency>

In the above dependencies we need to embed htmlcompressor dependency as we don't have in it AEM. We can either manually install the bundle or embed it from pom file.

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.

2 replies

May 9, 2018

Better to use gzip compression on the dispatcher. More efficient than this.

Peter_Puzanovs
Community Advisor
Community Advisor
May 9, 2018

Dear wimswims,

You are confusing minification and gzip. Gzip encodes data to make it smaller, whereas minification changes the output before encoding to make it smaller.

susheel, embed the artefact in your OSGi bundle instead of declaring it as a run time dependency to resolve this issue. You do not have to declare it as OSGi bundle if you want to use it as a library only in this bundle.

Regards,

Peter

susheel
susheelAuthor
May 9, 2018

I didn't get your point.Can you some example what you mean?

April 28, 2021

Hi @susheel 

I was trying to use HTML compressor designed by you but the dependency of htmlcompressor is not getting resolved after build. Can you please suggest what needs to be done to make it work?

December 27, 2021

Hi @bhushank1606 ,

I am also facing same issue. is it resolved to u? could u tell the fix