In this blogpost I will go through the basic functionality that the ClientLibraryFolder offers, and how you can utilize that within your page components.
The “clientlib” functionality will manage all your Javascript and CSS resources in your application. It takes cares of dependency management, merging files and minifying content.
The following application scenarios will be explained :
- multiple components with their own Javascript and CSS files
- global Javascript and CSS files
- apps folder is not available on the publish 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: Creating components and clientlib nodes
First we make a few components, in this example 3 components are used, we do this all via CRXDE-lite (http://localhost:4502/crx/de)
Next we are going to add a “clientlib” node of type cq:ClientLibraryFolder, inside this node the Javascript and CSS resources are stored.
Add a property to every clientlib-node called “categories” of type String[] with the single value of “myproject.components”. (To get a String[] type click the Multi button ).
Your components-folder will look now like this:
Step 2: Adding Javascript and CSS resources
Now we are going to add some simple 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 (mentions 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 components folder will now look like this:
The configuration of the components are now finished.
Step 3: Using clientlibs in your component
Now the setup of the clientlib is finished we can invoke the clientlibs in your page components. 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 article Sightly will be used for the examples.
We start with putting the following 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 following 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 publish instance)
- 6 server calls have to be made to fetch the resources
- Application structure is exposed
Step 4: redirecting resources via /etc/designs and merging into single files
What we want is that the user gets the resources from /etc/designs/<project>, so that /apps can be closed for the production configuration. And on top of that we want that the resources will be merged into a single .js/.css reference.
Create a new folder “aproject” in /etc/designs, then create the structure as shown below. The js.txt and css.txt should be empty files.
The clientlib-node has the following properties:
With the embed-property it embeds all the resources of “myproject.components”
Now change the call in the <head> section 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 following 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 references are now done via the /etc/designs folder.
Step 5: Dependencies
Another property you can add to the clientlib-node is “dependencies”, this way you can define dependencies between clientlibs.
Let’s add a dependency on cq.jquery:
When you now reload the page the dependency 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 better performance you can enable “Minify” and “Gzip” for the “Day CQ HTML Library Manager” in the Felix Configuration console (http://server/system/console/configMgr). These settings are recommended for production installations.
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 comments and spacing are removed to save download-time.
FAQ
Q: I don’t want to have all my Javascript references in the <head>
A: Move the data-sly-call to the right location in your template, you can use clientlib multiple times
A: Move the data-sly-call to the right location in your template, you can use clientlib multiple times
Q: Where are the generated files stored in CQ?
A: They are in /var/clientlibs
A: They are in /var/clientlibs
Q: When developing I want to have single file references in my HTML
A: Enable the debug-option in the HTML Library Manager
A: Enable the debug-option in the HTML Library Manager
Q: Is there a console so I can see the dependencies?
A: Yes, look at this page http://server/libs/cq/ui/content/dumplibs.html
A: Yes, look at this page http://server/libs/cq/ui/content/dumplibs.html
Q: Are there debugging options available?
A: Yes, ?debugClientLibs=true writes out single files
A: Yes, ?debugClientLibs=true and CTRL+SHIFT+U gives you timing info
A: Yes, ?debugClientLibs=true writes out single files
A: Yes, ?debugClientLibs=true and CTRL+SHIFT+U gives you timing info
Q: Can I rebuild the clientlibs?
A: Yes, via this url: /libs/granite/ui/content/dumplibs.rebuild.html
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 hashing of the url via ‘versioned clientlibs’.
A: You can enable the hashing of the url via ‘versioned clientlibs’.
Q: Do you have an example of this?
A: Yes, create a new project via the AEM-Archetype type via the Eclipse-plugin, all of this is included in there
A: Yes, create a new project via the AEM-Archetype type via the Eclipse-plugin, all of this is included in there
Q: What is the best practice with regards to performance 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 overall performance of your pages. All of this will happen in combination with the dispatcher.
A: Via mod_expires / mod_deflate and the use of cache-busting you can cache the css/js files on the browser to increase overall performance of your pages. All of this will happen in combination with the dispatcher.
No comments :
Post a Comment