Covers creation of AEM Client-Side Libraries or clientlibs to deploy and manage CSS and Javascript for an AEM Sites implementation. Integration with AEM's responsive grid and mobile emulator. aemfed module is used to accelerate front-end development.

Front-end Frameworks

Below are some of the front-end technologies used in the creation of the WKND site. The intention is to give you an idea of how 3rd party frameworks can easily be integrated into an AEM Site.

LESS- popular CSS pre-compiler that allows variables and other functionality. AEM client libraries natively support LESS compilation. Saas or other pre-compilers can be used but would need to be compiled outside of AEM.

Client-Side Libraries provide many ways for organization, below is a convention used by the WKND site and WE.Retail sites and can be applied to most Sites implementations.

High Level Clientlib Architecture

Site Client-Side Libraries

We will now implement Client-Side libraries that contain styles and javascript that will be applied site wide. This includes some global styles and brand variables to create a consistent look and feel.

Creating a client library is similar to creating any other type of node in AEM. The basic structure includes:

There are a lot of nodes and files for the WKND site client libraries. To expedite the tutorial (and to avoid tedious steps) install the below package that includes several important client libraries for the WKND site. This will provide a base-line of styles for some of the foundational HTML elements.

Client Libraries are considered code and thus are stored in the ui.apps module beneath /apps/wknd/clientlibs.

The AEM project archetype creates /apps/clientlibs/clientlib-base automatically. The below zip includes the source for the additional client libraries:

Download Chapter3-Clientlibs-Start.zip and unzip directly inside your project on the file system beneath ui.appps/src/main/content/jcr_root/apps/wknd/clientlibs. (make sure to only copy the folders within the zip archive)

In the ui.apps module there should now be a clientlibs folder beneath /apps/wknd. With 4 folders beneath the clientlibs folder:

Below we will inspect the new clientlibraries of clientlib-dependencies, clientlib-site, and clientlib-author.

clientlib-dependencies

This clientlibrary embeds some common AEM javascript dependencies that would be used for integrating analytics, ContextHub, CSRF protection and other Adobe marketing cloud offerings. The version of jquery that ships with AEM (/libs/clientlibs/granite/jquery) will be used. You can download a newer version of jquery and create a new client library if necessary.

The clientlib-dependencies typically consists mostly of Javascript. However since these dependencies are needed for features like ContextHub they will be included in the at the top of the page in the HTML head.

clientlib-site

This is the main client library for the WKND site. It includes site specific styles. It also includes two files named variables.less and mixins.less that establish some leverage features of LESS to ensure consistency.

Two files grid.less, main.less are inspected below in more detail.

Properties:

Name

Type

Value

Description
(tutorial info only don't copy)

jcr:primaryType

Name

cq:ClientLibraryFolder

defines a client library

allowProxy

Boolean

true

exposes CSS/JS via /etc.clientlibs

categories

String[]

wknd.site

category(s) that allows the clientlib to be referenced

main.less - /apps/wknd/clientlibs/clientlib-site/main.less

This is the entry point for all of the LESS styles in the client library. At the top of the file variables.less and mixins.less are imported to be able to share with the rest of the files. At the bottom of main.less you can see the inclusion of component specific styles. Notice the organization folder structure for the component specific files.The main.less also includeds a file named grid.less that will be responsible for creating AEM's responsive grid.

Generates the AEM responsive grid that will allow content authors to use all the capabilities of the AEM Layout Mode and the Layout Container. It uses a custom mixin found in grid_base.less to generate the grid. Notice that the Phone and Tablet breakpoints use variables found in the less/variables.less file. These breakpoints match the breakpoints defined in the empty template type: /conf/wknd/settings/wcm/template-types/empty-page/structure/jcr:content/cq:responsive/breakpoints.

Within clientlib-site you will also notice a folder named webfonts. This is a small clientlibrary that includes a call to Google webfonts. This has been split from the rest of clientlib-site in order to load this clientlibrary at the top of the CSS file. In the next section we will embed this clientlibrary as part of clientlib-base.

clientlib-author

As a best practice the code base for the Author environment should be nearly identical to the Publish environment. There are certain cases in which some extra CSS/JS is necessary to provide a better authoring experience. The WKND site has a fixed-header design and in the Editor this makes it difficult to select the Header component in edit mode. Therefore a small amount of CSS overrides will be stored in this client library and only loaded in the Author environment. This practice should be used sparingly and only when absolutely necessary.

Name

Type

Value

Description

jcr:primaryType

Name

cq:ClientLibraryFolder

defines a client library

categories

String[]

wknd.author

category(s) that allows the clientlib to be referenced

Update clientlib-base

clientlib-base

This clientlibrary, which is automatically generated by the archetype, represents the base level of CSS and JavaScript needed for the WKND site to function. This library won't include any CSS/JS files directly, instead it will include multiple client libraries via the embed property.

Update the embed property to include two WKND specific client libraries. Include wknd.webfonts as the first embed. Append wknd.site to the end of the String array.

Caution:

The order in which the embed array matters. It determines the order in which libraries are included. We want the webfonts to be loaded first and we want our site specific libraries to be loaded last to ensure we can override styles inherited from core components.

embeds the clientlibs by their respective category. Include any CoreComponent clientlibs here. Also including bootstrap but just the JS. LESS imports is used to include the rest of the bootstrap library. The wknd.site category embeds the clientlib-site library. wknd.webfonts is split and embedded at the top so that the webfonts are correctly imported at the top of the generated CSS file.

Several Core Components come with client libraries that need to be included on the page in order for the component to function properly. For example see /apps/core/wcm/components/image/v2/image/clientlibs.

There are two client libraries in this folder one named editor and another named site. The editor clientlib is meant just for the author environment and typically included by the component dialog. The site clientlib is the one that needs to be included in the project's clientlib in order for the component to behave properly. For each Core Component you can view the README.md to understand what each clientlib does: /apps/core/wcm/components/image/v2/image/README.md.

Implement Header Styles

Next we will implement some basic styles for the Header component. We want to make the header component behave as a "sticky" header and scroll with the page. We also want to resize the header to optimize for tablet/mobile views. LESS and JavaScript will be added to the clientlib-site library.

Implement Page Scroll listener

We will add a piece of javascript that will listen for a browser scroll and inject a CSS class into the body tag of the HTML page. We can then modify CSS based on this class change. We could have made this javascript specific to just the Header component, however we may want other scroll behavior across components. We will add this script with the global styles with the other page styles.

Beneath /apps/wknd/clientlibs/clientlib-site/components/page add a new file named page.js

The above function will add a CSS class named "scrolly" to the body tag whenever the scroll position changes form 0. This javascript depends on jQuery being loaded. The clientlib-dependencies library will include jQuery on the page.

Update /apps/wknd/clientlibs/clientlib-site/js.txt to include page.js. The js.txt and css.txt files in a client library act as a manifest for which files to be surfaced and the order in which they will be loaded. Simply adding a file in the client library is not enough to include it in library.

Update js.txt:

#base=.
components/page/page.js

Beneath /apps/wknd/clientlibs/clientlib-site/components create the following folder and file structure for the header styles:

Notice that at the bottom of the file we add a box-shadow to the header div based on the addition of the scrolly class name. The scrolly class name will be populated based on the JavaScript added earlier when the page scrolls.

Lastly, update /apps/wknd/clientlibs/clientlib-site/main.less to include the header.less style:

Adding Clientlibs to the Page

Next the clientlibs needed to be included via the base page. The Core Component page provides two files designed to include custom clientlibs in the html head for CSS and at the very bottom of the page for JavaScript. The AEM project archetype has already included the wknd.base client library.

Updates are needed to include wknd.dependencies and in the authoring environment wknd.author.

This includes the CSS for the wknd.base client library and the JS for the wknd.dependencies client library. Typically it is a best practice to include JS at the bottom of the page. The wknd.dependencies JS is used for loading libraries that support targeted content like ContextHub and so in this case it is a best practice to load it at the top of the page. The author-specific client library wknd.author is also loaded. Notice the wcmmode conditional, this means that only if the page is open in the Author editing environment will this client library be loaded. More information about the WCMMode can be found here.

ContextHub is a JS based framework for personalization, it is loaded in the header. This tutorial does not cover implementing ContextHub but more information about ContextHub can be found here.

View file customfooterlibs.html

This will be included at the very bottom of the page and will include the JS for wknd.base client library. It will override: /apps/core/wcm/components/page/v2/page/customfooterlibs.html. No changes are needed as the AEM project archetype created this file already.

The main takeaway is that the CSS and Javascript is dynamically loaded from a path that starts with /etc.clientlibs. The client libraries are stored beneath /apps/wknd to make it easier from an organizational standpoint as it is in the same directory as our component code. It is critical on the publish side that the client libraries are not served from /apps as this path should be restricted for security reasons using the Dispatcher filter section. The allowProxy property of the client library ensures the CSS and JS are served from /etc.clientlibs.

While view the page with wcmmode=disabled check that the scrolling header is working when the browser is sized > 992px.

Debugging Client Libraries

With different methods of categories and embeds to include multiple client libraries it can be cumbersome to troubleshoot. AEM exposes several tools to help with this. One of the most important tools is Rebuild Client Libraries which will force AEM to re-compile any LESS files and generate the CSS.

Dump Libs - Lists all of the client libraries registered in the AEM instance. <host>/libs/granite/ui/content/dumplibs.html

Test Output- allows a user to see the expected HTML output of clientlib includes based on category. <host>/libs/granite/ui/content/dumplibs.test.html

Rebuild Client Libraries - allows a user to force AEM to rebuild all of the client libraries or invalidate the cache of client libraries. This tool is particularly effective when developing with LESS as this can force AEM to re-compile the generated CSS. In general it is more effective to Invalidate Caches and then perform a page refresh versus rebuilding all of the libraries. <host>/libs/granite/ui/content/dumplibs.rebuild.html

Developing with aemfed

At a high level aemfed listens to file changes and automatically syncs the to a running AEM instance. Based on the changes, a local browser will automatically refresh, thereby speeding up front-end development. It also is built to work with Sling Log tracer to automatically display any serverside errors directly in the terminal. Full documentation can be found here.

Note:

We will now walk through the steps of installing aemfed globally. For the latest and greatest instructions make sure to check the official aemfed documentation.

A key part of aemfed is the ability to relay errors directly to the command line. To enable this behavior we need to update the configuration for Sling Log Tracer.

The storing of DAM assets outside of AEM and in source control is rare. If you are following the tutorial on the Git repo we have added the DAM assets to the project. This is to allow someone to pick up the tutorial at any point but the storing of a lot of assets in source control is not a best practice.