Best practices for Minify or Merge CSS and JS files in a aem-boilerplate-commerce project ? | Community
Skip to main content
elkinomnipro
New Member
July 8, 2025
Solved

Best practices for Minify or Merge CSS and JS files in a aem-boilerplate-commerce project ?

  • July 8, 2025
  • 1 reply
  • 1398 views

Hi everyone, good day!

 

What would you recommend as the best approach for minifying and merging files generated and added during the build process ?

 

As the projects grows, more and more style tags are being injected into the head section, so I think it would be better to merge and/or minify them into a few (or even just one) to improve site performance.

 

Additionally, do you have any recommendations or best practices for efficiently loading styles and scripts, especially when dealing with third-party providers such as GTM, Zendesk, etc.?

 

Thanks in advance for your insights!

 

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by SantoshSai

@rabiirahmouni 

1. Build Pipeline Integration: Monorepo vs. Split Repos for ClientLibs

Best Practice: Keep the frontend build tooling co-located within the AEM repo, especially for Content and Experience-Driven projects (like AEM Commerce).

Why:

  • Tighter integration with the ui.apps structure (eg. clientlibs paths)

  • Easier local dev experience using mvn clean install and npm run build

  • Simplifies deployment via Cloud Manager or Jenkins pipelines

Alternative (if you're scaling fast):

  • Use a separate frontend repo (monorepo style or micro-frontend-based)

  • Output the final /dist or /build assets directly to:

    ui.apps/src/main/content/jcr_root/apps/<project>/clientlibs/<bundle>
  • Sync it using a Git submodule, CI/CD artifact copy step, or symbolic linking (npm run build:copy-to-clientlib)

Choose this route if you have independent teams maintaining design systems or shared components across multiple sites.

2. Performance Monitoring of Page-Type Bundling

Absolutely - here’s how we measure performance gains per bundle:

Core Web Vitals (CWV) – Our Go-To Metrics:

  • LCP (Largest Contentful Paint) -> most sensitive to CSS blocking

  • FID (First Input Delay) -> influenced by JS bundle execution

  • CLS (Cumulative Layout Shift) -> mostly layout CSS + async script order

Tools We Use:

  • Lighthouse CI -> integrate into PR validation

  • WebPageTest -> simulate 3G/mobile loads

  • New Relic / Datadog RUM -> enterprise-level Real User Monitoring

  • Adobe Monitoring (Cloud Manager pipeline also gives some CWV)

  • Custom window.performance.mark() hooks to measure JS load time for each bundle

Bundle-level Tracking:

We use bundle-specific names (eg. pdp-bundle.js, plp.css) and:

  • Track in browser DevTools -> see which bundle blocks rendering

  • Set up performance budgets in Webpack -> alert on bloat

3. Lazy-Loading 3rd-Party Scripts w/ Intersection Observer

Yes! Intersection Observer (IO) is game-changing for fine-tuned lazy-loading of widgets like chat, reviews, recommendation carousels, etc.

Example: Lazy-load Zendesk on visibility

const loadZendesk = () => {
  const script = document.createElement('script');
  script.src = 'https://static.zdassets.com/ekr/snippet.js?...';
  script.async = true;
  document.body.appendChild(script);
};

const observer = new IntersectionObserver((entries, obs) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      loadZendesk();
      obs.disconnect();
    }
  });
}, { threshold: 0.25 });

const target = document.getElementById('zendesk-widget-placeholder');
if (target) observer.observe(target);

This keeps the main thread clean during page load and improves TTI/FID scores dramatically.

4. Scaling Page-Type Bundling with Large Product Catalogs

Yes, it scales extremely well, if you scope bundles smartly.

Strategy:

  • Bundle per layout complexity, not SKU volume.

    • eg. PLP = grid + filter UI, PDP = tabs + image zoom.

  • Reuse shared libraries (react, swiper, etc.) via vendor chunking (eg. vendor.js)

  • Use code splitting with Webpack dynamic import() for:

    • Size charts

    • Reviews

    • Personalized recommendations

1 reply

SantoshSai
Community Advisor
Community Advisor
July 8, 2025

Hi @elkinomnipro,

1. Use Frontend Build Tools (Webpack/Vite) for Optimization

Handle all minification and bundling in your frontend pipeline before deployment:

  • Bundle and minify your CSS and JS during build time.

  • Output to AEM clientlibs:

    /apps/your-project/clientlibs/site/ ├── css.txt → includes minified CSS ├── js.txt → includes minified JS
  • Reference these in your page component using:

    <sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html" data-sly-call="${clientlib.all @ categories='your.project.site'}"/>

2. ClientLibs Configuration for Production

In your clientlibs/site/.content.xml:

<jcr:root jcr:primaryType="cq:ClientLibraryFolder" categories="[your.project.site]" allowProxy="{Boolean}true" versioned="{Boolean}true" jsProcessor="[default:none,min:gcc]" cssProcessor="[default:none,min:none]"/>

This ensures:

  • Minification using Google Closure Compiler (min:gcc)

  • Versioned assets for better cache control

  • Delivery via /etc.clientlibs with CDN support

3. Smart Merging Strategy

Instead of creating one large file:

  • Bundle by page type (e.g., home, PLP, PDP)

  • Keep third-party scripts separate for lazy loading

  • Use async/defer for non-critical JS

4. Efficient 3rd-Party Script Loading (GTM, Zendesk, etc.)

  • Load critical third-party scripts like GTM in <head> with async:

    <script async src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXX"></script>
  • Defer others like Zendesk or chat widgets until:

    • User scrolls

    • After first interaction

    • Using requestIdleCallback() or similar

You can also create a separate clientlib (eg. clientlibs/zendesk) and load it only on needed pages.

Santosh Sai
Level 4
July 9, 2025

Hi @santoshsai ,

 

Just to clarify,  question is specifically related to a project based on Adobe Edge Delivery Services, using the aem-boilerplate-commerce starter. In this architecture, we are not using Maven archetypes or traditional AEM clientlibs, so the recommendations about /apps/.../clientlibs and .content.xml don’t apply in this context.

 

Since all styles and scripts are injected during the build process and pushed to the Git repository, @elkinomnipro  is looking for best practices around optimizing CSS and JS inside this Git-based setup, such as:

 

How to bundle and minify styles/scripts before they get injected into the final HTML output (e.g., in blocks, scripts, styles folders).

 

Recommendations for modular loading, especially as the number of blocks increases.

 

Efficient handling of third-party scripts (like GTM or Zendesk), possibly through lazy loading or deferred injection strategies tailored for EDS.

 

If anyone in the EDS community has tackled similar challenges in aem-boilerplate or similar setups, We’d love to hear how you approached this.

 

Thanks again!