Html minification using AEM 6.1
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.

