Client libraries and front-end workflow client-side-libraries
Learn how Client-Side Libraries or clientlibs are used to deploy and manage CSS and JavaScript for an Adobe Experience Manager (AEM) Sites implementation. This tutorial also covers how the ui.frontend module, a de-coupled webpack project, can be integrated into the end-to-end build process.
Prerequisites prerequisites
Review the required tooling and instructions for setting up a local development environment.
It is also recommended to review the Component Basics tutorial to understand the fundamentals of client-side libraries and AEM.
Starter Project
Check out the base-line code that the tutorial builds on:
-
Check out the
tutorial/client-side-libraries-start
branch from GitHubcode language-shell $ cd aem-guides-wknd $ git checkout tutorial/client-side-libraries-start
-
Deploy code base to a local AEM instance using your Maven skills:
code language-shell $ mvn clean install -PautoInstallSinglePackage
note note NOTE If using AEM 6.5 or 6.4, append the classic
profile to any Maven commands.code language-shell $ mvn clean install -PautoInstallSinglePackage -Pclassic
You can always view the finished code on GitHub or check out the code locally by switching to the branch tutorial/client-side-libraries-solution
.
Objectives
- Understand how client-side libraries are included onto a page via an editable template.
- Learn how to use the
ui.frontend
module and a webpack development server for dedicated front-end development. - Understand the end-to-end workflow of delivering compiled CSS and JavaScript to a Sites implementation.
What you are going to build what-build
In this chapter, you add some baseline styles for the WKND site and the Article Page Template to bring the implementation closer to the UI design mockups. You use an advanced front-end workflow to integrate a webpack project into an AEM client library.
Article Page with baseline styles applied
Background background
Client-Side Libraries provide a mechanism to organize and manage CSS and JavaScript files necessary for an AEM Sites implementation. The basic goals for client-side libraries or clientlibs are:
- Store CSS/JS in small discrete files for easier development and maintenance
- Manage dependencies on third-party frameworks in an organized fashion
- Minimize the number of client-side requests by concatenating CSS/JS into one or two requests.
More information about using Client-Side Libraries can be found here.
Client-side libraries do have some limitations. Most notably is a limited support for popular front-end languages like Sass, LESS, and TypeScript. In the tutorial, let’s look at how the ui.frontend module can help solve this.
Deploy the starter code base to a local AEM instance and navigate to http://localhost:4502/editor.html/content/wknd/us/en/magazine/guide-la-skateparks.html. This page is unstyled. Let’s implement Client-side libraries for the WKND brand to add CSS and JavaScript to the page.
Client-Side Libraries Organization organization
Next let’s explore the organization of clientlibs generated by the AEM Project Archetype.
High-level diagram Client-side Library organization and page inclusion
-
Using VSCode or other IDE open up the ui.apps module.
-
Expand the path
/apps/wknd/clientlibs
to view the clientlibs generated by the archetype.In the below section, these clientlibs are reviewed in greater details.
-
The following table summarizes the client libraries. More details about including Client Libraries can be found here.
table 0-row-3 1-row-3 2-row-3 3-row-3 4-row-3 Name Description Notes clientlib-base
Base level of CSS and JavaScript needed for WKND Site to function embeds Core Component client libs clientlib-grid
Generates the CSS necessary for Layout Mode to work. Mobile/Tablet breakpoints can be configured here clientlib-site
Contains site-specific theme for the WKND Site Generated by the ui.frontend
moduleclientlib-dependencies
Embeds any third-party dependencies Generated by the ui.frontend
module -
Observe that
clientlib-site
andclientlib-dependencies
are ignored from source control. This is by design, since these are generated at build time by theui.frontend
module.
Update base styles base-styles
Next, update the base styles defined in the ui.frontend module. The files in the ui.frontend
module generate the clientlib-site
and clientlib-dependecies
libraries that contain the Site theme and any third-party dependencies.
Client-side libraries do not support more advanced languages like Sass or TypeScript. There are several open-source tools like NPM and webpack that accelerate and optimize front-end development. The goal of the ui.frontend module is to be able to use these tools to manage most front-end source files.
-
Open up the ui.frontend module and navigate to
src/main/webpack/site
. -
Open the file
main.scss
main.scss
is the entry point to the Sass files in theui.frontend
module. It includes the_variables.scss
file, which contains a series of brand variables to be used throughout different Sass files in the project. The_base.scss
file is also included and defines some basic styles for HTML elements. A regular expression includes the styles for individual components styles undersrc/main/webpack/components
. Another regular expression includes the files undersrc/main/webpack/site/styles
. -
Inspect the file
main.ts
. It includesmain.scss
and a regular expression to collect any.js
or.ts
files in the project. This entry point is used by the webpack configuration files as the entry point for the entireui.frontend
module. -
Inspect the files beneath
src/main/webpack/site/styles
:These files styles for global elements in the template, like the Header, Footer and main content container. The CSS rules in these files target different HTML elements
header
,main
, andfooter
. These HTML elements were defined by policies in the previous chapter Pages and Templates. -
Expand the
components
folder undersrc/main/webpack
and inspect the files.Each file maps to a Core Component like the Accordion Component. Each Core Component is built with Block Element Modifier or BEM notation to make it easier to target specific CSS classes with style rules. The files beneath
/components
have been stubbed out by the AEM Project Archetype with the different BEM rules for each component. -
Download the WKND Base Styles wknd-base-styles-src-v3.zip and unzip the file.
To accelerate the tutorial, several Sass files that implement the WKND brand based on Core Components and the structure of the Article Page Template is provided.
-
Overwrite the contents of
ui.frontend/src
with files from the previous step. The contents of the zip should overwrite the following folders:code language-plain /src/main/webpack /components /resources /site /static
Inspect the changed files to see details of the WKND style implementation.
Inspect the ui.frontend integration ui-frontend-integration
A key integration piece built into the ui.frontend module, aem-clientlib-generator takes the compiled CSS and JS artifacts from a webpack/npm project and transforms them into AEM client-side libraries.
The AEM Project Archetype automatically sets up this integration. Next, explore how it works.
-
Open a command-line terminal and install the ui.frontend module using the
npm install
command:code language-shell $ cd ~/code/aem-guides-wknd/ui.frontend $ npm install
note note NOTE npm install
run is needed only once, like after a new clone or generation of the project. -
Open
ui.frontend/package.json
and in the scripts start command add--env writeToDisk=true
.code language-json { "scripts": { "start": "webpack-dev-server --open --config ./webpack.dev.js --env writeToDisk=true", } }
-
Start the webpack dev server in watch mode by running the following command:
code language-shell $ npm run watch
-
This compiles the source files from the
ui.frontend
module and syncs the changes with AEM at http://localhost:4502code language-shell + jcr_root/apps/wknd/clientlibs/clientlib-site/js/site.js + jcr_root/apps/wknd/clientlibs/clientlib-site/js + jcr_root/apps/wknd/clientlibs/clientlib-site + jcr_root/apps/wknd/clientlibs/clientlib-dependencies/css.txt + jcr_root/apps/wknd/clientlibs/clientlib-dependencies/js.txt + jcr_root/apps/wknd/clientlibs/clientlib-dependencies http://admin:admin@localhost:4502 > OK + jcr_root/apps/wknd/clientlibs/clientlib-site/css + jcr_root/apps/wknd/clientlibs/clientlib-site/js/site.js http://admin:admin@localhost:4502 > OK
-
The command
npm run watch
ultimately populates the clientlib-site and clientlib-dependencies in the ui.apps module which is then synced automatically with AEM.note note NOTE There is also a npm run prod
profile which minifies the JS and CSS. This is the standard compilation whenever the webpack build is triggered via Maven. More details about the ui.frontend module can be found here. -
Inspect the file
site.css
beneathui.frontend/dist/clientlib-site/site.css
. This is the compiled CSS based on the Sass source files. -
Inspect the file
ui.frontend/clientlib.config.js
. This is the configuration file for an npm plugin, aem-clientlib-generator that transforms the contents of/dist
into a client library and moves it to theui.apps
module. -
Inspect the file
site.css
in the ui.apps module atui.apps/src/main/content/jcr_root/apps/wknd/clientlibs/clientlib-site/css/site.css
. This should be an identical copy of thesite.css
file from the ui.frontend module. Now that it is in ui.apps module it can be deployed to AEM.note note NOTE Since clientlib-site is compiled during build time, using either npm, or maven, it can be safely ignored from source control in the ui.apps module. Inspect the .gitignore
file beneath ui.apps. -
Open the LA Skatepark article in AEM at: http://localhost:4502/editor.html/content/wknd/us/en/magazine/guide-la-skateparks.html.
You should now see the updated styles for the article. You may need to do a hard refresh to clear any CSS files cached by the browser.
It’s starting to look a lot closer to the mockups!
note note NOTE The steps performed above to build and deploy the ui.frontend code to AEM is executed automatically when a Maven build is triggered from the root of the project mvn clean install -PautoInstallSinglePackage
.
Make a style change
Next, make a small change in the ui.frontend
module to see the npm run watch
automatically deploy the styles to the local AEM instance.
-
From, the
ui.frontend
module open the file:ui.frontend/src/main/webpack/site/_variables.scss
. -
Update the
$brand-primary
color variable:code language-scsss //== variables.css //== Brand Colors $brand-primary: $pink;
Save the changes.
-
Return to the browser and refresh the AEM page to see the updates:
-
Revert the change to the
$brand-primary
color and stop the webpack build using the commandCTRL+C
.
Page and Template Inclusion page-inclusion
Next, let’s review how the clientlibs are referenced in the AEM Page. A common best practice in web development is to include CSS in the HTML Header <head>
and JavaScript right before closing </body>
tag.
-
Browse to the Article Page template at http://localhost:4502/editor.html/conf/wknd/settings/wcm/templates/article-page/structure.html
-
Click the Page Information icon and in the menu select Page Policy to open the Page Policy dialog.
Page Information > Page Policy
-
Notice that the categories for
wknd.dependencies
andwknd.site
are listed here. By default clientlibs configured via the Page Policy are split to include the CSS in the page head and the JavaScript at the body end. You can explicitly list the clientlib JavaScript be loaded in the Page head. This is the case forwknd.dependencies
.note note NOTE It is also possible to reference the wknd.site
orwknd.dependencies
from the page component directly, using thecustomheaderlibs.html
orcustomfooterlibs.html
script. Using the Template gives flexibility in that you can pick and choose which clientlibs are used per template. For example, if you have a heavy JavaScript library that is only going to be used on a select template. -
Navigate to the LA Skateparks page created using the Article Page Template: http://localhost:4502/editor.html/content/wknd/us/en/magazine/guide-la-skateparks.html.
-
Click the Page Information icon and in the menu select View As Published to open the article page outside of the AEM Editor.
-
View the Page source of http://localhost:4502/content/wknd/us/en/magazine/guide-la-skateparks.html?wcmmode=disabled and you should be able to see the following clientlib references in the
<head>
:code language-html <head> ... <script src="/etc.clientlibs/wknd/clientlibs/clientlib-dependencies.lc-d41d8cd98f00b204e9800998ecf8427e-lc.min.js"></script> <link rel="stylesheet" href="/etc.clientlibs/wknd/clientlibs/clientlib-dependencies.lc-d41d8cd98f00b204e9800998ecf8427e-lc.min.css" type="text/css"> <link rel="stylesheet" href="/etc.clientlibs/wknd/clientlibs/clientlib-site.lc-78fb9cea4c3a2cc17edce2c2b32631e2-lc.min.css" type="text/css"> ... </head>
Notice that the clientlibs are using the proxy
/etc.clientlibs
endpoint. You should also see that the following clientlib includes at the bottom of the page:code language-html ... <script src="/etc.clientlibs/wknd/clientlibs/clientlib-site.lc-7157cf8cb32ed66d50e4e49cdc50780a-lc.min.js"></script> <script src="/etc.clientlibs/wknd/clientlibs/clientlib-base.lc-53e6f96eb92561a1bdcc1cb196e9d9ca-lc.min.js"></script> ... </body>
note note NOTE For AEM 6.5/6.4 the client-side libraries are not automatically minified. See the documentation on the HTML Library Manager to enable minification (recommended). note warning WARNING 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.
Next Steps next-steps
Learn how to implement individual styles and reuse Core Components using Experience Manager’s Style System. Developing with the Style System covers using the Style System to extend Core Components with brand-specific CSS and advanced policy configurations of the Template Editor.
View the finished code on GitHub or review and deploy the code locally at on the Git branch tutorial/client-side-libraries-solution
.
- Clone the github.com/adobe/aem-wknd-guides repository.
- Check out the
tutorial/client-side-libraries-solution
branch.
Additional Tools and Resources additional-resources
Webpack DevServer - Static Markup webpack-dev-static
In the previous couple of exercises several Sass files in the ui.frontend module were updated and through a build process, ultimately see that these changes reflected in AEM. Next let’s look at a technique that uses a webpack-dev-server to rapidly develop the front-end styles against static HTML.
This technique is handy if most the styles and front-end code is performed by a dedicated Front-End developer who may not have easy access to an AEM environment. This technique also allows the FED to make modifications directly to the HTML, which can then be handed off to an AEM developer to implement as components.
-
Copy the page source of the LA skatepark article page at http://localhost:4502/content/wknd/us/en/magazine/guide-la-skateparks.html?wcmmode=disabled.
-
Reopen your IDE. Paste the copied markup from AEM into the
index.html
in the ui.frontend module beneathsrc/main/webpack/static
. -
Edit the copied markup and remove any references to clientlib-site and clientlib-dependencies:
code language-html <!-- remove --> <script type="text/javascript" src="/etc.clientlibs/wknd/clientlibs/clientlib-dependencies.js"></script> <link rel="stylesheet" href="/etc.clientlibs/wknd/clientlibs/clientlib-dependencies.css" type="text/css"> <link rel="stylesheet" href="/etc.clientlibs/wknd/clientlibs/clientlib-site.css" type="text/css"> ... <script type="text/javascript" src="/etc.clientlibs/wknd/clientlibs/clientlib-site.js"></script>
Remove these references because the webpack dev server generates these artifacts automatically.
-
Start the webpack dev server from a new terminal by running the following command from within the ui.frontend module:
code language-shell $ cd ~/code/aem-guides-wknd/ui.frontend/ $ npm start > aem-maven-archetype@1.0.0 start code/aem-guides-wknd/ui.frontend > webpack-dev-server --open --config ./webpack.dev.js
-
This should open a new browser window at http://localhost:8080/ with static markup.
-
Edit the file
src/main/webpack/site/_variables.scss
file. Replace the$text-color
rule with the following:code language-diff - $text-color: $black; + $text-color: $pink;
Save the changes.
-
You should automatically see the changes automatically reflected in the browser on http://localhost:8080.
-
Review the
/aem-guides-wknd.ui.frontend/webpack.dev.js
file. This contains the webpack configuration used to start the webpack-dev-server. It proxies the paths/content
and/etc.clientlibs
from a locally running instance of AEM. This is how the images, and other clientlibs (not managed by the ui.frontend code) are made available.note caution CAUTION The image src of the static markup points to a live image component on a local AEM instance. Images appear broken if the path to the image changes, if AEM is not started, or if the browser has not logged into the local AEM instance. If handing off to an external resource, it’s also possible to replace the images with static references. -
You can stop the webpack server from the command line by typing
CTRL+C
.
aemfed develop-aemfed
aemfed is an open-source, command-line tool that can be used to speed up front-end development. It is powered by aemsync, Browsersync, and Sling Log Tracer.
At a high level, the aemfed
is designed to listen to file changes within the ui.apps module and automatically sync them directly to a running AEM instance. Based on the changes, a local browser automatically refreshes, thus speeding up front-end development. It is also built to work with Sling Log tracer to automatically display any server-side errors directly in the terminal.
If you are doing much work within the ui.apps module, modifying HTL scripts, and creating custom components, aemfed can be a powerful tool to use. Full documentation can be found here.
Debugging Client-side Libraries debugging-clientlibs
Using 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 forces AEM to recompile any LESS files and generate the CSS.
-
Dump Libs - Lists 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
-
Libraries Dependencies validation - highlights any dependencies or embedded categories that cannot be found.
<host>/libs/granite/ui/content/dumplibs.validate.html
-
Rebuild Client Libraries - allows a user to force AEM to rebuild the client libraries or invalidate the cache of client libraries. This tool is effective when developing with LESS as this can force AEM to recompile the generated CSS. In general, it is more effective to Invalidate Caches and then perform a page refresh versus rebuilding the libraries.
<host>/libs/granite/ui/content/dumplibs.rebuild.html