Expand my Community achievements bar.

SOLVED

Questions about Best Practices with JS in AEM - Webpack, jQuery, Third-Party JS

Avatar

Level 1

We have both classic and Touch UI implementations of AEM, so I have some experience dealing with these issues in the classic environment. Right now, we are trying to find the best approach with Touch UI and Webpack. We have a frontend that is a custom framework along with custom components (that need their own JS and maybe CSS). I'd appreciate any help for the following:

 

  1. For third-party jQuery-dependent vendor JavaScript (not installed through Node), we have tried adding them in Webpack, but then we encounter the standard problem of making them available in the global namespace for custom component JS to access. For example, vendor JS like DataTables and Bootstrap-Select have globally available methods $().DataTable() or $().selectpicker() that are not available when added in Webpack. This appears to be by design with Webpack.
    1. How should vendor JS be loaded, especially JS that builds on jQuery?
    2. Currently, clientlib-site JS gets loaded at the bottom of the page. Custom component clientlibs for JS gets added within the page where the component is added. How do I solve issues with global functions not existing for the custom component JS because they have not been loaded yet (because that JS is at the bottom of the page)?
    3. How could we specify vendor JS (e.g., DataTables) to be loaded only when a specific custom component is used on a page?
  2. For custom components with their own JS,
    1. How do we architect the JS file structure? Should the component JS be housed in the component's folder within apps as it has historically been? Or should all JS now be housed under Webpack's folder structure to enable modular JavaScript features?
    2. If the JS is housed in Webpack and built out inside the site.js file, how can we change the structure in a way that allows the component JS to be loaded only on the pages where the component is used rather than be loaded for all pages?

 

 

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi,

 

First of all, Classic UI is deprecated, and it’s highly recommended that you avoid making any customizations in it. Instead, you should consider using the Modernizer Tools to help upgrade to TouchUI wherever possible.

Now, let me address your questions. This is a complex topic, so I’ll do my best to explain it. Keep in mind that everything depends on your specific project and use case, but here are my thoughts:

Q1.1 Third-party/vendor scripts

This depends on where the scripts are being used. From what I understand, these scripts are broadly used throughout the site, and you'll likely need to define them globally. One option is to wrap all "mandatory" scripts into a dedicated client library (clientlib) and load it as eagerly as possible. Out of the box, the new AEM archetypes define a "clientlib-dependencies" structure for this type of script. However, keep in mind that this approach might have performance implications. You can either use the out-of-the-box clientlib or create your own using the clientlib node package. Once that's done, you can load the clientlib through the Template's Page Policy, which gives you several useful options for loading in the head or footer asynchronously. https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/how-does-the-aem-client-li... https://github.com/adobe/aem-project-archetype/blob/39638e96235d21a05722def8120deb94277de14a/src/mai... 

Q1.2 Script execution timing

This can be solved if you load the critical JS eagerly, as mentioned above. Another approach would be to trigger custom JS events as the JS loads. You can then refactor your JS to listen for those custom events and execute the necessary code only after the events are fired. More info: https://experienceleague.adobe.com/en/docs/experience-manager-learn/getting-started-wknd-tutorial-de...  https://stackoverflow.com/questions/436411/where-should-i-put-script-tags-in-html-markup  https://medium.com/@prakashvb404/multiple-ways-to-call-client-libs-in-aem-a-guide-for-developers-93c... 

Q1.3 Code splitting and dynamic imports

You can utilize code splitting and dynamic imports via Webpack to optimize the loading of JavaScript. Reference: https://blog.3sharecorp.com/aem-code-splitting-dynamic-imports-typescript 

Q2.1 JavaScript creation

The JS should be created in the ui.frontend module to take full advantage of Webpack and modern JavaScript tools. For examples: https://medium.com/@roy007/unleashing-ui-frontend-in-aem-ee361acb1f1b https://drewrobinson.com/blog/aem-frontend-module-overview https://unlocklearning.in/aem-frontend-development-with-ui-frontend-module/ 

Q2.2 Code splitting and dynamic imports (again)

Similar to the previous point, you can use code splitting and dynamic imports from Webpack to achieve this. Reference: https://blog.3sharecorp.com/aem-code-splitting-dynamic-imports-typescript 

 

Hope this helps.



Esteban Bustamante

View solution in original post

1 Reply

Avatar

Correct answer by
Community Advisor

Hi,

 

First of all, Classic UI is deprecated, and it’s highly recommended that you avoid making any customizations in it. Instead, you should consider using the Modernizer Tools to help upgrade to TouchUI wherever possible.

Now, let me address your questions. This is a complex topic, so I’ll do my best to explain it. Keep in mind that everything depends on your specific project and use case, but here are my thoughts:

Q1.1 Third-party/vendor scripts

This depends on where the scripts are being used. From what I understand, these scripts are broadly used throughout the site, and you'll likely need to define them globally. One option is to wrap all "mandatory" scripts into a dedicated client library (clientlib) and load it as eagerly as possible. Out of the box, the new AEM archetypes define a "clientlib-dependencies" structure for this type of script. However, keep in mind that this approach might have performance implications. You can either use the out-of-the-box clientlib or create your own using the clientlib node package. Once that's done, you can load the clientlib through the Template's Page Policy, which gives you several useful options for loading in the head or footer asynchronously. https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/how-does-the-aem-client-li... https://github.com/adobe/aem-project-archetype/blob/39638e96235d21a05722def8120deb94277de14a/src/mai... 

Q1.2 Script execution timing

This can be solved if you load the critical JS eagerly, as mentioned above. Another approach would be to trigger custom JS events as the JS loads. You can then refactor your JS to listen for those custom events and execute the necessary code only after the events are fired. More info: https://experienceleague.adobe.com/en/docs/experience-manager-learn/getting-started-wknd-tutorial-de...  https://stackoverflow.com/questions/436411/where-should-i-put-script-tags-in-html-markup  https://medium.com/@prakashvb404/multiple-ways-to-call-client-libs-in-aem-a-guide-for-developers-93c... 

Q1.3 Code splitting and dynamic imports

You can utilize code splitting and dynamic imports via Webpack to optimize the loading of JavaScript. Reference: https://blog.3sharecorp.com/aem-code-splitting-dynamic-imports-typescript 

Q2.1 JavaScript creation

The JS should be created in the ui.frontend module to take full advantage of Webpack and modern JavaScript tools. For examples: https://medium.com/@roy007/unleashing-ui-frontend-in-aem-ee361acb1f1b https://drewrobinson.com/blog/aem-frontend-module-overview https://unlocklearning.in/aem-frontend-development-with-ui-frontend-module/ 

Q2.2 Code splitting and dynamic imports (again)

Similar to the previous point, you can use code splitting and dynamic imports from Webpack to achieve this. Reference: https://blog.3sharecorp.com/aem-code-splitting-dynamic-imports-typescript 

 

Hope this helps.



Esteban Bustamante