DEV Community

Natalia Venditto
Natalia Venditto

Posted on • Updated on

Integrating a modern frontend in a multi tenant AEM project (part 1)

I felt it was about time I found a moment to write this article. I am sure that more than one frontend developer (especially in the role of tech lead or frontend architect) working in AEM projects, will find it useful. It's very important you understand that the advise I give here is my sole opinion and preferences, but it's backed up by 5 years of experience as Frontend Tech Lead in large enterprise platforms built on top of AEM.

Like every architecture topic, it is a bit dense, so I will split it into different subtopics, for it to be easier to follow.

Tech stack

I will presuppose that the whole project is structured following the Maven Archetype https://maven.apache.org/guides/introduction/introduction-to-archetypes.html (or the Adobe Archetype, in the best of cases), and obviously, that Maven is the compilation tool to put it together. Other assumptions, you're using at least version 6.3 of AEM, Maven 3.5+, Java8, and Sling Models. (Although the backend tech matters little, to be honest, the Maven version does not)

In the frontend, our stack will be ES6 (no frameworks for now, but we will integrate one at a later step -aka a new post- ), we will use Redux for state management, and obviously our html will be written as HTL templates. Ready to go?

Folder Structure

The first thing you need to consider, is your folder structure. And to decide your folder structure, you may need to work together with your backend tech leads or solution architect.

Usually they will have a strong opinion on the subject, and the (client) requirements will play a major role. Let's work on the hypothesis of having a large enterprise project between hands. That will imply perhaps, a lot of sub-projects under a common dependency. Each one of those, we will call 'tenants'.

So let's propose the following structure (I know it will look familiar to people working with AEM, so I won't go into details).
In our hypothetical project, the sling models are in our core package, the .html files (HTL files), the dialogues, etc, will be in our components package, together with the common frontend files used by all tenants (javascript vendor, abstracts and shared sass code), the frontend files (js and sass) files for each one of the tenants, will be in a their respective tenants/tenant-name package. Notice that tenants is a module on its own.

Clientlibs

If you've been working with AEM for a while, as a frontend or backend developer, you're very likely familiar with AEM's pattern for frontend code, the client-side libraries (known by AEM devs as clientlibs). You can read more about them here -> https://helpx.adobe.com/experience-manager/6-4/sites/developing/using/clientlibs.html

Clientlibs are categorised, (precisely by declaring a category name for each one of them), and you can have as many categories as you wish (hold that thought!). AEM as a system downloads its own core clientlibs, (think granite for example, that makes all authoring interface dialogues work etc). This clientlib, has a dependency on jQuery, so you have jQuery available in the frontend if you need it, even if you don't introduce it yourself. (Of course, you're restricted to a particular version!).

Remember when I said you can have all the clientlibs you wish to have? Well, in theory, you can. In practice, you probably want to make that decision depending on the protocol that will be serving your site. If it's http/2, (and I encourage you to fight for that!) you may have a clientlib category per component or module. Conversely, if you're on HTTP 1.1, then you are probably better aggregating all your bundles into one, and serving them as a single category per 'wcmmode' (author or preview/publish). That's an important decision at the time of designing your frontend build. So you please make that question early to your DevOps team or architect. We will speak about aggregation and compression, in a later post.

Please notice that AEM supports compilation of LESS natively. But we won't use it. We will do our CSS pre processing on our own.

Components

In the latest versions of AEM, it is a good practice to classify components per content or structure, meaning whether they have a structural function or will be dragged and dropped into the content. I believe that's a great utility to understand what may be a common asset or component, and what serves a more dedicated, specific role.

With that in mind, let's look at what the structure inside of a tenant may look like:

Additionally, inside of each component folder, you would have a

  • componentname.entry.scss
  • componentname.entry.js
  • componentname.config.js (optional when necessary)

Shared, abstract and vendor

Earlier in this post we mentioned these categories and explained that they're recommended to exist in a common dependency. By shared and abstract we mean for example utility code such as mixins, functions, maps, and global variables that serve for the purpose of making those work.

Since this code is consumed by all tenants, we will place it in the components package. Not only it makes 0 sense to repeat this code several times, it does not make sense to maintain it several times. It also does not belong in the tenants space, where only tenant specific code must be.

Now we have added all these, our structure looks something like the one below.

Frontend Build

Now we can finally get to the fun part. Installing and configuring our frontend build. I recommend this global frontend build to be in a separate module. If you want to know more about it (what technologies we will be using, how we will configure it to grab our entries, etc), read the next post, !

And while I write it, you can watch this video:

Top comments (25)

Collapse
 
pgangwani profile image
pgangwani

I am using spa template given by adobe. Currently stuck with integrating parsys in column control or layout grid component. Can you help ?

Collapse
 
thomasjithin profile image
Jithin Thomas

Hi Pavan, Nice to meet again, were you able to handle the nested component in SPA framework ? I've gone through your code. Were you able to handle this usecase, i would like to get more info about this. - Jithin

Collapse
 
anfibiacreativa profile image
Natalia Venditto

I would love to, but I am afraid I need a bit more information to be able to help...

Collapse
 
pgangwani profile image
pgangwani

I am following this template --> helpx.adobe.com/in/experience-mana...

I have usecase to create nested components using grid (column control) which loop over equal size cell , now each cell should have "drag component" aem parsys so that any component can be added.
So I want pointers for such example. Unfortunately, Adobe's doc's are unclear for this usecase.

Can you help ?

If you need any further sharing of code leme know or any other pointers.

Thnaks in advance

Thread Thread
 
anfibiacreativa profile image
Natalia Venditto

Hi, I would definitely need more information. What does exactly not work for you. Column control implements a parsys or responsivegrid component inside of each partition, so to speak. You should have a policy defining the components allowed in that container.

Thread Thread
 
pgangwani profile image
pgangwani

That where I need help to refer some example.

Thread Thread
 
anfibiacreativa profile image
Natalia Venditto

Do you have this code somewhere I could see? Like in a public repo?

Thread Thread
 
pgangwani profile image
pgangwani • Edited

give me 1 hr , leme clone the repo and remove internal stuff before sharing.

Thread Thread
 
anfibiacreativa profile image
Natalia Venditto

github -> @anfibiacreativa

Thread Thread
 
pgangwani profile image
pgangwani

Here you go: github.com/pgangwani/aem-react-pre...

Pl check column control: It should include childcomponents as added in comment

Thread Thread
 
pgangwani profile image
pgangwani

Added you as collaborator , can push directly if you found any thing fishy or small mistake

Thread Thread
 
pgangwani profile image
pgangwani

Hello Natalia, did you get chance to check the code ?

Thread Thread
 
anfibiacreativa profile image
Natalia Venditto

Hi :) No, it may take a bit. Unfortunately, it is a week with a lot of work for me ;)Thanks for being patient.

Thread Thread
 
pgangwani profile image
pgangwani

Thanks for letting me know. I can wait... :)

Thread Thread
 
pgangwani profile image
pgangwani

Hello Natalia, were you able to access the code

Thread Thread
 
anfibiacreativa profile image
Natalia Venditto

Hi Pawan. Today I had a little time to quickly take a look but your issue is not with AEM per se (as this article describes a modern yet independent to AEM Frontend Setup) but with the React implementation in the context of AEM SPA editor. So I am not sure I can help there. According to this npmjs.com/package/@adobe/cq-react-... You should be extending ResponsiveGrid and implementing something like { super.childComponents } inside of your div.

Thread Thread
 
anfibiacreativa profile image
Natalia Venditto

"Container.childComponents()
Returns the child components of this Container. It will iterate over all the items and instantiate the child components if a Mapping is found Instantiation is done my connecting the Component with the data of that item"

Thread Thread
 
pgangwani profile image
pgangwani

I tried that too , didn't work. Do you have AEM 6.5 ? Can you try and share the screen shot of console of printing child components. When I checked I got empty array. 🙄

Thread Thread
 
gopikrishna123 profile image
G.K.

@pgangwani Do you have any update on this Usecase, I have tried the same and getting CQItems as empty array, when I try to use Model to get dialog values. Please let me know if you have solution on this. thanks in advance!!

Collapse
 
ahmedmusallam profile image
Ahmed Musallam

Nice to see some AEM content on dev.to!!! Way to go!

I’ve contemplated posting AEM content here, but I always stop at the fact that there might not be an audience for it... plus I write most of that stuff on my employer’s site :)

Anyway! Awesome post! And would love to see more!!

Collapse
 
anfibiacreativa profile image
Natalia Venditto

Thank you. Second part, where I explain the actual webpack config and maven integration, coming next. :)

Collapse
 
ahmedmusallam profile image
Ahmed Musallam

Ah, you should make use of this: dev.to/ben/changelog-create-series...

Collapse
 
ashokajin profile image
ashokAjin

We are using native JavaScript and es6 features.
Page renders on server and only dynamic events are handled at front-end. Which is mostly static and is rendered on server. what folder structure we have to follow. pls do let me know

Collapse
 
munikmca profile image
Muneeswar Reddy

Very good article! Very well articulated.

Collapse
 
anfibiacreativa profile image
Natalia Venditto

Thank you. Part II is almost ready, so stay tuned!