Arti­cle updat­ed on Feb 11, 2018

In this blog post, I will go through the basic func­tion­al­i­ty that the ClientLi­brary­Fold­er offers, and how you can uti­lize that with­in your page com­po­nents.

Please note that I will use the proxy clientlibs approach, this is avail­able and rec­om­mend­ed since AEM6.2

The AEM Client Library (or ClientLib) func­tion­al­i­ty will man­age all your JavaScript and CSS resources in your appli­ca­tion. It takes cares of depen­den­cy man­age­ment, merg­ing files and mini­fy­ing con­tent (remov­ing unnec­es­sary white spaces).

The fol­low­ing appli­ca­tion sce­nar­ios will be explained:

  • mul­ti­ple com­po­nents with their own JavaScript and CSS files
  • CSS resources have to go in the <head>, JavaScript resources at the end of the page
  • Resources need to be mini­fied
  • chang­ing the mini­fi­ca­tion engine

Let’s get start­ed!

Step 1: Creating components and ClientLib nodes

First we make a few com­po­nents, in this exam­ple 3 com­po­nents are used, we do this all via CRXDE-lite (http://localhost:4502/crx/de).

clientlibs1

Next we are going to add a “clientlib” node of type “cq:ClientLibraryFolder”, inside this node the JavaScript and CSS resources are stored.

clientlibs2

Add a prop­er­ty to every “clientlib” node called “cat­e­gories” of type String[] with the sin­gle val­ue of “myproject.components” (to get a String[] type click the “Mul­ti” but­ton).

clientlibs3

Now add a Boolean prop­er­ty “allow­Proxy”, and set this to true. This will make the clientlibs avail­able via the url /etc.clientlibs/, so it means they are not hav­ing the /apps ref­er­ence.

Your com­po­nents-fold­er will look now like this:

clientlibs4

Step 2: Adding JavaScript and CSS resources

Now we are going to add some sim­ple JavaScript and CSS resources in the “clientlib” nodes.

Cre­ate fol­low­ing files inside of your “clientlib” fold­er of “MyFirst­Com­po­nent”:

first.css

.firstContainer {
    margin-top:10px;
}

first.js

/*
 * This is the comment of the function
 */
function getNameFirst() {
    // return the name
    return "some value";
}

js.txt

# mentions all the JavaScript resources of the ClientLib
first.js

css.txt

# mentions all the CSS resources of the ClientLib
first.css

And repeat the same thing for the oth­er com­po­nents to achieve some­thing that looks like this:

clientlibs5

The con­fig­u­ra­tion of the com­po­nents are now fin­ished.

Step 3: Using ClientLibs in your component

Now the set­up of the ClientLib is fin­ished we can invoke the ClientLibs in your page com­po­nents. When you are using a JSP you can use cq:includeClientlib . In case you are using the HTML Tem­plate Lan­guage (HTL), you can use the data-sly-call to invoke the ClientLib. In this arti­cle HTL will be used for the exam­ples.

We start with putting the fol­low­ing into the <head> ele­ment of our page:

<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html" />
<sly data-sly-call="${clientlib.css @ categories='myproject.components'}" />
<sly data-sly-call="${clientlib.js @ categories='myproject.components'}" />

The val­ue of the “cat­e­gories” prop­er­ties of the “clientlib” nodes are “myproject.components”, which is what we need to pro­vide above.

This results in the fol­low­ing HTML-out­put:

<link rel="stylesheet" href="etc.clientlibs/mycomponents/MyThirdComponent/clientlib.css" type="text/css">
<link rel="stylesheet" href="etc.clientlibs/mycomponents/MySecondComponent/clientlib.css" type="text/css">
<link rel="stylesheet" href="etc.clientlibs/mycomponents/MyFirstComponent/clientlib.css" type="text/css">
<script type="text/javascript" src="etc.clientlibs/mycomponents/MyThirdComponent/clientlib.js"></script>
<script type="text/javascript" src="etc.clientlibs/mycomponents/MySecondComponent/clientlib.js"></script>
<script type="text/javascript" src="etc.clientlibs/mycomponents/MyFirstComponent/clientlib.js"></script>

This has a few down­sides:

  • 6 serv­er calls have to be made to fetch the resources.
  • Appli­ca­tion struc­ture is exposed.

Step 4: Merging files

To merge the sev­er­al clientlib files into one, we define a clientlibs that is embed­ding the oth­er cat­e­gories. Exam­ple here is tak­en from /app­s/w­ere­tail/­clientlib­s/­clientlib-base.

Step 5: Dependencies

Anoth­er prop­er­ty you can add to the “clientlib” node is “depen­den­cies”, this way you can define depen­den­cies between ClientLibs.

Let’s add a depen­den­cy on “cq.jquery”:

clientlibs8

When you now reload the page the depen­den­cy is writ­ten:

<script type="text/javascript" src="https://blogsimages.adobe.com/etc/clientlibs/foundation/jquery.js"></script>
<script type="text/javascript" src="https://blogsimages.adobe.com/etc.clientlibs/myproject/clientlib.js"></script>

Step 6: Minify and Gzip

To deliv­er a bet­ter per­for­mance you can enable “Mini­fy” and “Gzip” for the “Adobe Gran­ite HTML Library Man­ag­er” (pre­vi­ous­ly also called “Day CQ HTML Library Man­ag­er”), in the Felix Con­fig­u­ra­tion con­sole (http://server/system/console/configMgr). These set­tings are rec­om­mend­ed for pro­duc­tion instal­la­tions.

clientlibs9

By default the YUI com­pres­sor is used when mini­fy­ing files, you can bet­ter use the GCC (Google Clo­jure Com­pil­er) for this.

This is described here: https://helpx.adobe.com/experience-manager/kb/how-to-change-the-minification-engine-for-client-libraries-in-AEM.html

Common error with proxy clientlibs

When you use proxy clientlibs, then you may run into this error:

Unable to proxy yourfont.ttf. No sup­port­ed type for .ttf”, this can hap­pen for types oth­er than JS/CSS.

Rea­son for this is that resources oth­er than JS/CSS need to be put into a fold­er called resources.

Exam­ple here on we-retail : https://​github​.com/​A​d​o​b​e​-​M​a​r​k​e​t​i​n​g​-​C​l​o​u​d​/​a​e​m​-​s​a​m​p​l​e​-​w​e​-​r​e​t​a​i​l​/​t​r​e​e​/​m​a​s​t​e​r​/​u​i​.​a​p​p​s​/​s​r​c​/​m​a​i​n​/​c​o​n​t​e​n​t​/​j​c​r​_​r​o​o​t​/​a​p​p​s​/​w​e​r​e​t​a​i​l​/​c​l​i​e​n​t​l​i​b​s​/​c​l​i​e​n​t​l​i​b​-​s​ite

 

FAQ

Q: I don’t want to have all my JavaScript ref­er­ences in the <head>
A: Move the data-sly-call to the right loca­tion in your tem­plate, you can use ClientLib mul­ti­ple times

Q: Where are the gen­er­at­ed files stored in AEM?
A: They are stored in /var/clientlibs

Q: When devel­op­ing I want to have sin­gle file ref­er­ences in my HTML
A: Enable the debug-option in the HTML Library Man­ag­er

Q: Is there a con­sole so I can see the depen­den­cies?
A: Yes, look at this page http://server/libs/cq/ui/content/dumplibs.html

Q: Are there debug­ging options avail­able?
A: Yes, ?debugClientLibs=true writes out sin­gle files

Q: Can I rebuild the ClientLibs?
A: Yes, via this url: /libs/granite/ui/content/dumplibs.rebuild.html

Q: How can I use cache-bust­ing and ClientLibs?
A: You can enable the hash­ing of the url via ‘ver­sioned ClientLibs’.

Q: Do you have an exam­ple of this?
A: Yes, the “core” com­po­nents can be used as a reference: https://git.corp.adobe.com/CQ/aem-core-wcm-components

Q: What is the best prac­tice with regards to per­for­mance and caching
A: Via mod_expires / mod_deflate and the use of cache-bust­ing you can cache the css/js files on the brows­er to increase over­all per­for­mance of your pages. All of this will hap­pen in com­bi­na­tion with the dis­patch­er.

@heervisscher

Read-on

Relat­ed to the ClientLib top­ic, I also wrote an arti­cle HTL and client libraries, which gives some addi­tion­al details on the aspects relat­ed to the HTML Tem­plate Lan­guage, and also pro­vides an exam­ple on how to pass data from the serv­er-side log­ic to the client-side code.