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.

5 comments
Matthieu
Matthieu

It seems to me that your article has wrong information. In your step 3, you write:


<cq:includeClientLib css=“myproject.components” />

<cq:includeClientLib js=“myproject.components” />


Isn't it what you write in your component to register your clientLib, (and not to write out the html) ? Maybe this article should just be unpublished.


Matthieu
Matthieu

Can you please restore the images ?

Guest
Guest

If AEM is supposed to be such a great tool for building and managing web assets and communities, why is your web presence, particularly for AEM, so incredibly and globally BROKEN?

karunssss
karunssss

Screenshots are broken and are not visible... please upload..!!