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.
Better to use gzip compression on the dispatcher. More efficient than this.
Views
Replies
Total Likes
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
Views
Replies
Total Likes
I didn't get your point.Can you some example what you mean?
Views
Replies
Total Likes
Dear susheel
You have two options, make that bundle OSGi compatible[1]
or
You can use Apache Felix - Apache Felix Maven Bundle Plugin (BND) embed dependency configuration to add your jar directly to your bundle, not ask it to be picked up as a externally provided bundle.
[1] how to embed dependent jar ?
Regards,
Peter
Views
Replies
Total Likes
Thank you
Views
Replies
Total Likes
In the past I was indeed thinking the same, but the overhead of doing whitespace compression is much bigger than the gain of just enabling gzip compression on the non-minified content. Gzip is pretty good in compressing spaces as well.
More at https://www.peterbe.com/plog/html-whitespace-compression and Any reason not to strip whitespace in HTML - Stack Overflow.
Even so, some HTML elements should not be stripped from whitespace (see Collapse Whitespace ). In my opinion, it isn't worth the extra complexity.
Views
Replies
Total Likes
You are right but html compression plugin is smart enough to take care of all those issues. Here gzip is already enabled and it does great job of compression. But by removing white space 20% more was saved.
Views
Replies
Total Likes
This is along with gzip encoding. Extra compression
Views
Replies
Total Likes
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?
Views
Replies
Total Likes
Hi @bhushank1606 ,
I am also facing same issue. is it resolved to u? could u tell the fix
Views
Replies
Total Likes
Views
Likes
Replies
Views
Likes
Replies
Views
Likes
Replies