Thursday, June 22, 2017

ClientLibs in AEM 6.3 - Part1


Hello Everyone,

Clientlibs is one of my favorite concepts of AEM and frequently asked in interviews.There is a lot of information available on internet regarding same. Lets discuss some of the concept related to clientlibs in this blog...

Below are the questions which hits your mind when you think about clientlibs:
  • What are Client-Side Libraries?
  • Why Client-Side Libraries?
  • Feature or Properties of Clientlibs
  • Tips and Tricks over the concept of Clientlibs

Let's explore the answers for all above ...

What are Client-Side Libraries?

➤ Modern websites rely heavily on client-side processing driven by complex JavaScript and CSS code. Organizing and optimizing the serving of this code can be a complicated issue.

To deal with this issue, AEM provides the concept of Client-Side Library Folder which allows you to store client side code in the repository, organize it into categories and decide when and how each category code is served to the client.

Client side libraries play a very crucial role to provide rich functionality to end user. Clientlibs  is used to manage these libraries in AEM.

Why Client-Side Libraries?

Client-Side Libraries include JS and CSS files. Below is the traditional way of using these on any web page:

<head>
<link rel="stylesheet"href="/etc/clientlibs/aem-developer/css/test.css">
<script type="text/javascript"src="/etc/clientlibs/aem-developer/js/test1.js"></script>
<script type="text/javascript" src="/etc/clientlibs/aem-developer/js/test.js"></script>
</head>

In the above code, there will be separate network call for each js and css file.

But think, if hundreds of CSS and JS files present in website, then each file will have a network call due to which overall performance will be reduced as load time of a web page will increase gradually.


No. of Request  Page load Time

So AEM came up with a better approach. Only two calls will be there for single clientlibs, one for js and another for CSS.

Irrespective of number of CSS file present, only single CSS call will be there and all css file will be embedded in same call and same applicable for JS file as well.

How to Create Client-Side Library Folder

Steps to follow:
1.Go to any folder where you want to locate a client library Folder.Create a Node here of type cq:clientLibraryFolder.
2.To specify the categories ,add the property in the clientLibraryFolder like this:
  • Name : Categories     
  • Type : String[]    
  • Value : category_name
3.Add source files(css and js files) to the categories.You can organise these files in subfolders as well.
4.Select the clientLibraryFolder, and create the following files:
  • js.txt: Use this file to generate java script file.
  • css.txt: Use this file to generate css file.
5.In the above files,add the base to identify the root of the source files.
#base=[root]
Replace [root] with the path of the folder that contains the source files,relative to the txt files.

If all the source files are in the same folders of the txt files.Use this
#base=.

If all the source files are under a specific folder i.e. mobile 
#base=mobile

How AEM manage the ClientLibs?

There are two ways to include client-side libraries in your page but it depends on what we are using (JSP or HTL), But nowadays HTL is very popular in AEM.

In HTL (Sightly): 

<div data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}"/>
 <sly data-sly-call="${clientLib.all @ categories='apps.aem-learning'}"/>

Note: In HTL,client libraries are loaded through a helper template(/libs/granite/sightly/templates/clientlib.html) provided by AEM.

This helper template expects a categories option for referencing the desired client libraries.That option can be either an array of string values, or a string containing a comma separated values list.

Note: Here keyword “all” stands for all the JS and CSS files.If you want to call js and CSS specifically, replace all keyword with “CSS” or “JS”.

In JSP: 
<%@taglib prefix="ui"uri="http://www.adobe.com/taglibs/granite/ui/1.0" %>
<ui:includeClientLib categories="<%= categories %>" />

Use below if you want to use CSS specifically, 
<ui:includeClientLib css="apps.aem-learning"/>

Use below  if you want to use JS specifically,

<ui:includeClientLib js="apps.aem-learning"/>

The generated HTML page contains the following code:

<link rel="stylesheet" href=”/etc/clientlibs/aem-developer.css" type="text/css"></link>
<script type="text/javascript" src="/etc/clientlibs/aem-developer.js"></script>

Note: <cq:includeClientLib> which in the past was commonly used to include client libraries, has been deprecated since AEM 5.6.<ui:includeClientLib> should be used instead as detailed above.

Feature or Properties of ClientLibs

  • Categories: This property uniquely identifies the Clientlibs and a Clientlibs can be included in a page using categories.The categories property being multi-valued,allows a library folder to be the part of more than one category.
Note: It is advisable to preface the category value by ‘apps’ or ‘etc’ to specify the location of Clientlibs.

  • Dependencies: There is a list of other client-side libraries on which the library folder depends.

To identify dependencies, add a property to your cq:ClientLibraryFolder node with the following attributes:

dependencies.PNG
Fig - dependencies property in clientlib folder

  • Name: dependencies
  • Type: String[]
  • Values: The value of the categories property of the cq:ClientLibraryFolder node that the current library folder depends on.
Example: If clientlib  A is having B as a dependency.Then 4 network calls will exist.First B will get executed because A tries to resolve all its dependencies and then A  executes itself.
<link rel="stylesheet" href=”/etc/clientlibs/sgaem/B.css" type="text/css">
<script type="text/javascript" src="/etc/clientlibs/sgaem/B.js"></script>
<link rel="stylesheet" href=”/etc/clientlibs/sgaem/A.css" type="text/css">
<script type="text/javascript" src="/etc/clientlibs/sgaem/A.js"></script>

Note: Dependencies property is transitive – if Clientlib A depends on B and B depends on C, then all clientlibs will be included in the page in the order of C>B>A.

  • Embed: It is used to embed code from other libraries. Use the categories property to identify the client library folder to embed. To embed the library, add a property to the embedding cq:ClientLibraryFolder node, using the following property attributes:

embed.PNG
Fig- embed property in clientlib folder
  • Name: embed
  • Type: String[]
  • Value: The value of the categories property of the cq:ClientLibraryFolder node that the current library folder embed upon.
Example: If clientlibs B is embed with A ,then only 2  network calls will exist. B will be concatenated with A's  content in itself and only A will be seen in the network call.

Note: Name of final JS or CSS  file will be same as the parent client-library. Here A is the parent client-library folder.
<link rel="stylesheet" href=”/etc/clientlibs/sgaem/A.css" type="text/css">
<script type="text/javascript" src="/etc/clientlibs/sgaem/A.js"></script>

This property reduces a large number of network calls for clientlibs.


Note: Embed property is NOT transitive – If Clientlib A embed B and B embed C, then only A and B will be included in the page,but C won't. In order to include Clientlib C, it must be added to the embed property of A as well.



Tips and Tricks over the concept of clientlibs

Let's troubleshoot What happens when:

Clientlibs A is dependent on B,B is dependent on C

ClinetlibExample1 (1).jpg
Fig- Example of nested dependencies property

CSS Calls:
<link rel="stylesheet" href=”/etc/clientlibs/aem-developer/C.css" type="text/css">
<link rel="stylesheet" href=”/etc/clientlibs/aem-developer/B.css" type="text/css">
<link rel="stylesheet" href=”/etc/clientlibs/aem-developer/A.css" type="text/css">

JS Calls:

<script type="text/javascript" src="/etc/clientlibs/aem-developer/C.js"></script>
<script type="text/javascript" src="/etc/clientlibs/aem-developer/B.js"></script>
<script type="text/javascript" src="/etc/clientlibs/aem-developer/A.js"></script>

A category tries to solve its dependency and B also does the same,that’s why C is being called very first and after that B and A.

Clientlibs A is embed on B,B is embed on C.

ClinetlibExample2 (1).jpg
Fig- Example of nested embed property

Embed doesn’t provide transitive addition that’s why only A and B is being called.B is embedded in A calls.

<link rel="stylesheet" href=”/etc/clientlibs/aem-developer/A.css" type="text/css">
<script type="text/javascript" src="/etc/clientlibs/aem-developer/A.js"></script>

Clientlibs A is dependent on B,B is dependent on C and C is dependent on A

Note:No clientlibs is getting called as it becomes the condition of infinite loop

Clientlibs A is embed on B,B is embed on A.

Note: It will work same as scenario:2 as B doesn’t consider its embed to be resolved because embed doesn’t have transitive addition.


Clientlibs A is embed on B and dependent on C.

ClinetlibExample5 (1).jpg
Fig- Example of embed with dependencies property

If a clientlibs will have both dependency and embed,then it’s priority will be to resolve dependency at first and then embed.

NO. of CSS calls:

<link rel="stylesheet" href=”/etc/clientlibs/aem-developer/C.css" type="text/css">
<link rel="stylesheet" href=”/etc/clientlibs/aem-developer/A.css" type="text/css">

NO. of JS Calls:

<script type="text/javascript" src="/etc/clientlibs/aem-developer/C.js"></script>
<script type="text/javascript" src="/etc/clientlibs/aem-developer/A.js"></script>

After all this interesting stuff,clientlibs is not over yet.So stay tune and wait for our next blog.

If you have any query or suggestion then kindly comment or mail us at sgaem.blog02@gmail.com
Hope it will help you guys !!
Thanks and Happy Learning .😊

23 comments:

  1. Awesome one. Wish to see more like this.

    ReplyDelete
  2. Saurabh - One of the best article on client libs. Every thing is so easily explained.

    ReplyDelete
    Replies
    1. thanks satyam, such kind of appreciation always motivate us!!

      Delete
  3. awesome.. only missing content is minified css and js. please cover that also

    ReplyDelete
    Replies
    1. Thanks michael!!
      Sure, We will cover this topic in upcoming clientlibs blogs.

      Delete
  4. Awesome article. Simple and clear

    ReplyDelete
  5. Great explanation.
    Please explain embed property into deep with taking examples.

    ReplyDelete
  6. Thanks Saurabh.Is there a way to make the clientlib spit out
    --link rel="preload" href=”/etc/clientlibs/aem-developer/C.css" type="text/css"--
    instead of rel=stylesheet which is the default?(shown below)
    --link rel="stylesheet" href=”/etc/clientlibs/aem-developer/C.css" type="text/css"--

    ReplyDelete
  7. Did you find solve for clientlib preload?

    ReplyDelete
  8. Wonderful article , kudos mate on the great work done

    ReplyDelete
  9. y do we need a multi for the categories ?

    ReplyDelete
  10. How to resolve this A embeds B, B is dependent on C and C is dependent on D

    ReplyDelete
  11. Thanks.

    I used to saw a design config is needed, so we don’t need it anymore after 6.3?

    ReplyDelete
  12. Hi Shivani,

    Can we include JS on a page without using clientlib in aem 6.3?

    ReplyDelete
    Replies
    1. Yes We can always do that. ideally it is not a pure AEM way but can do.

      Delete
  13. Is there a way to find out in html of component if respective client library is loaded on the page ?

    ReplyDelete
  14. Can we include many js files in a folder and include that folder name only in js.txt file ?

    ReplyDelete