It's time we complete the series. Let's talk about AEM and maven!
In order to have the the frontend setup trigger tasks directly from maven, you will need to install a plugin in maven. But where?
As we previously discussed, the frontend module is both an npm package, and a maven plugin with its own pom.xml. However, we don't want to install the maven-frontend-plugin in this module, simply because it does not make sense.
Our intention is that, whenever we build the root project, or each tenant
individually, we trigger the frontend build as well (or we don't! up to us and the profile we pass!)
The plugin is fairly well documented, so I suggest you start by reading the documentation
The first thing we need to do is update our reactor pom.xml like this:
Let's analyse this, and first pay attention to the line number 23.
This is where we will define some properties that are important for our frontend build to run. Anything under
properties is also inherited by children poms so you don't have to repeat it, but you can overwrite it.
As you can see, you also pass some arguments the plugin needs to:
- install node and npm
- run the build
- rebuild node-sass (I will explain this later)
as well as some environmental variables, like what is the mode
By default, the mode is
production. That's what you want to run in Jenkins (and anywhere not your developer machine, really!)
You can also specify the versions for both node and npm
I imagine if you're reading here, you're more of frontend developer without, maybe, a lot of knowledge of Java or Maven or poms (which is completely fine!), so basically is good if we explain that in the line 36, we are defining the order of execution of all the children modules, of the reactor pom.xml.
The frontend module, should be the first one to be executed!
Again in line 48, I made some (illegal :P ) comment annotations. It's important you put the plugin goals in the
build session, wrapped by the
pluginManagement tags, because that's the way to extend it to the children modules.
This is basically standard for every implementation of this plugin. And as you can see, it is using definitions from the
properties in line 23.
One important configuration value is this one
The frontend working directory is always relative to the current pom, so you will have to override it in every tenant module pom.xml
Not only you can define profiles to run things. You can skip them. Like we already discussed in part 2. the frontend build can take quite some time and the backend guys may not need it.
If you pay attention to line 147, you can see that a profile to skip execution is provided
But how can you build a single tenant...and more! How does the frontend build and maven know to pass the right package every time?
That's an important question, that we can answer with code ;)
As you can see, this is the pom.xml that we would find in every
Is important you see that we're in fact overriding the value of
workingDirectory and making it relative to this file.
This is how we trigger the npm run build with the declared arguments as properties in the parent pom, but we of course do not need to install node and npm in this case.
You may also have noticed the following environment variable assignation
And if you go back to the part 2 of this series and take a look at the
project.paths.config.js file, you will realise that's exactly where that environmental variable is coming from. And this is how maven triggers a new frontend build, with the right tenant path, and traverses all relevant directories collecting entries, for each tenant individually.
Well, that's something you can do, too! The only aspect to remember is that you will need to assign the value for
NPM_FRONTEND_MODULE_BASE_DIR directly in the terminal, right before you run the command, or, this
Ok, now you have an idea how to construct a frontend build in the context of an AEM large scale project with multiple tenants, you have an idea of what tools to use and how to structure your files, configurations and tasks, how to trigger the build from the frontend module with npm and how with the maven-frontend-plugin with maven... Now you can input entry files and generate bundles as entries, but...
How do you request those bundles as clientlibs in your pages when you're developing and in your production site?!
Originally I wanted to split this in 3 parts of a series, but AEM is a complex world. If you want to know how to
- hot reload your code with watchers and aemsync while developing (not to lose your mind waiting for the whole maven build to run!)
- create clientlibs categories that make sense and
- request your clientlibs code in your components or templates using Context Aware Configurations
wait for the 4th and last part of this series and the repository in Github, to conclude this adventures. You will need to wait until I am back from holidays though!