Friday 13 November 2015

How to Work With Clientlibs In AEM/CQ5

In this blog­post I will go through the basic func­tion­al­ity that the ClientLi­brary­Folder offers, and how you can uti­lize that within your page components.
The “clientlib” func­tion­al­ity will man­age all your Javascript and CSS resources in your appli­ca­tion. It takes cares of depen­dency man­age­ment, merg­ing files and mini­fy­ing content.
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
  • global Javascript and CSS files
  • apps folder is not avail­able on the pub­lish instance
  • CSS resources have to go in the <head>, Javascript resources at the end of the page
  • Resources need to be minified
  • Some resources need to be merged

Let’s get started!

Step 1: Cre­at­ing com­po­nents 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­erty to every clientlib-node called “cat­e­gories” of type String[] with the sin­gle value of “myproject.components”. (To get a String[] type click the Multi button ).
clientlibs3
Your components-folder 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-node.
CSS (first.css):
.firstContainer {
margin-top:10px;
}

Javascript (first.js)
/*
* This is the comment of the function
*/
function getNameFirst() {
  // return the name
  return "some value";
}
js.txt (men­tions all the Javascript resources of the clientlib, in this case one line)
first.js
css.txt (same as for js.txt, but then for all the CSS resources, so also one line)
first.css
Your com­po­nents folder will now look like this:
clientlibs5
The con­fig­u­ra­tion of the com­po­nents are now finished.

Step 3: Using clientlibs in your component

Now the setup 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 Sightly you can use the data-sly-call to invoke the clientlib. In this arti­cle Sightly will be used for the examples.
We start with putting the fol­low­ing into the <head>
<sly data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}" data-sly-unwrap/>
<sly data-sly-call="${clientLib.css @ categories='myproject.components'}" data-sly-unwrap/>
<sly data-sly-call="${clientLib.js @ categories='myproject.components'}" data-sly-unwrap/>
Note that “myproject.components” is the value of the “categories”-properties of the clientlib-node. This results in the fol­low­ing HTML-output:
<link rel="stylesheet" href="/apps/mycomponents/MyThirdComponent/clientlib.css" type="text/css">

<link rel="stylesheet" href="/apps/mycomponents/MySecondComponent/clientlib.css" type="text/css">

<link rel="stylesheet" href="/apps/mycomponents/MyFirstComponent/clientlib.css" type="text/css">

<script type="text/javascript" src="/apps/mycomponents/MyThirdComponent/clientlib.js"></script>

<script type="text/javascript" src="/apps/mycomponents/MySecondComponent/clientlib.js"></script>

<script type="text/javascript" src="/apps/mycomponents/MyFirstComponent/clientlib.js"></script>
This has a few downsides:
  • The resources are retrieved from /apps (/apps is blocked on the pub­lish instance)
  • 6 server calls have to be made to fetch the resources
  • Appli­ca­tion struc­ture is exposed

Step 4: redi­rect­ing resources via /etc/designs and merg­ing into sin­gle files

What we want is that the user gets the resources from /etc/designs/<project>, so that /apps can be closed for the pro­duc­tion con­fig­u­ra­tion. And on top of that we want that the resources will be merged into a sin­gle .js/.css reference.
Cre­ate a new folder “apro­ject” in /etc/designs, then cre­ate the struc­ture as shown below. The js.txt and css.txt should be empty files.
clientlibs6
The clientlib-node has the fol­low­ing properties:
clientlibs7
With the embed-property it embeds all the resources of “myproject.components”
Now change the call in the <head> sec­tion to:
<sly data-sly-call="${clientLib.css @ categories='myproject.all'}" data-sly-unwrap/>
<sly data-sly-call="${clientLib.js @ categories='myproject.all'}" data-sly-unwrap/>
This results now in the fol­low­ing HTML output:
<link rel="stylesheet" href="/etc/designs/aproject/clientlib.css" type="text/css">

<script type="text/javascript" src="/etc/designs/aproject/clientlib.js"></script>
If you open these files you will see that the three js/css resources are merged into one file. And although the resources are located in the /apps-folder all ref­er­ences are now done via the /etc/designs folder.

Step 5: Dependencies

Another prop­erty 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­dency on cq.jquery:
clientlibs8
When you now reload the page the depen­dency is written:
<script type="text/javascript" src="/etc/clientlibs/foundation/jquery.js"></script>

<script type="text/javascript" src="/etc/designs/aproject/clientlib.js"></script>

Step 6: Minify and Gzip

To deliver a bet­ter per­for­mance you can enable “Minify” and “Gzip” for the “Day CQ HTML Library Man­ager” in the Felix Con­fig­u­ra­tion con­sole (http://server/system/console/configMgr). These set­tings are rec­om­mended for pro­duc­tion installations.
clientlibs9
When you now look at this resource “/etc/designs/aproject/clientlib.js”, it results in this:
function getNameThird(){return "some value";}
function getNameSecond(){return "some value";}
function getNameFirst(){return "some value";};
So all com­ments and spac­ing are removed to save download-time.

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­ated files stored in CQ?
A: They are 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 Manager
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
A: Yes, ?debugClientLibs=true and CTRL+SHIFT+U gives you tim­ing info
Q: Can I rebuild the clientlibs?
A: Yes, via this url: /libs/granite/ui/content/dumplibs.rebuild.html
Q: How can I use cache-busting 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, cre­ate a new project via the AEM-Archetype type via the Eclipse-plugin, all of this is included in there
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-busting you can cache the css/js files on the browser to increase over­all per­for­mance of your pages. All of this will hap­pen in com­bi­na­tion with the dis­patcher.

No comments :

Post a Comment