Overview

System - Bundler automatically combines multiple JavaScript and CSS files into optimized bundles, dramatically improving your site's performance.

Problem: Modern Joomla sites typically load 40+ separate JavaScript and CSS files on every page. Each file is a separate HTTP request, slowing down page load times.

Solution: Bundler combines these files into just 2-4 optimized bundles, minifies them, and compresses them with gzip.

Real Results:

  • 90% fewer HTTP requests (40 files → 4 bundles)
  • 70-80% smaller file sizes (with gzip compression)
  • Automatic updates when extensions are installed or updated
  • Zero ongoing maintenance after initial setup

Installation

  1. Download the plugin package
  2. Go to System → Extensions → Install
  3. Upload and install the package
  4. Go to System → Plugins
  5. Find System - Bundler and enable it
  6. Click the plugin name to configure it

Quick Start Guide

That's an oxymoron for this plugin - there isn't a quick way to use it.  You either plan, test, and iterate - or you don't use it at all.  It's that simple, which is to say - it isn't simple at all.  This plugin allows you to achieve an objective in a way that no other plugin can offer.  Once configured, it will deliver the same results time-and-time again.  Making changes is relatively simple, but your success depends on your willingness to go through the necessary steps to achieve success.

Developer Note:

You'll have great success bundling CSS, so start there.  That's where you'll find your biggest gains.  Common CSS on RicheyWeb.com went from 12 scripts to 2.  Defer-only scripts are bundled together - reducing 5 scripts to 1, and defer+async scripts were bundled together - reducing 3 scripts to 1. Steps to success can be found below. Attention to detail pays off with this plugin.

Step 1: Identify Site-Wide Assets

CRITICAL: Only bundle assets that load on EVERY page of your site.

Good candidates:

  • Template core files
  • Bootstrap framework files
  • System-level plugins
  • Site-wide navigation/footer assets

Bad candidates:

  • Component-specific scripts
  • Conditionally-loaded modules
  • Page-specific features

Step 2: Create Your First Bundle

  1. In plugin settings, click Add Bundle
  2. Set Bundle Name: scripts-main
  3. Set Type: JavaScript
  4. Set Attributes: (leave empty for now)
  5. Add files (see next section)
  6. Save the plugin

Step 3: Test

  1. Visit your homepage
  2. Open browser DevTools (F12)
  3. Go to Network tab
  4. Refresh page
  5. Look for plg_system_bundler/scripts-main_[version].js
  6. Verify original files are no longer loading

Understanding Asset Specification

This is the most important section. Read it carefully.

System - Bundler gives you TWO ways to specify which assets to bundle. Understanding the difference is critical.

Method 1: By File Path (Automatic Detection)

How it works:

  • You specify the file's URI/path
  • Plugin scans WebAssetManager on its first page load
  • If an asset with that URI is found, it's removed and bundled
  • If not found on this page, nothing happens

When to use:

  • The asset loads on every page (or most pages)
  • You can easily identify the file path
  • You want the plugin to automatically detect the asset

Example:

File: media/system/js/core.js
Asset: (leave blank)

How to find file paths:

  1. Open browser DevTools → Network tab
  2. Reload your page
  3. Look for .js or .css files
  4. Copy the path (e.g., media/system/js/core.js)

Method 2: By Asset Name (Explicit Control)

How it works:

  • You specify the asset's registration name
  • Plugin ALWAYS removes this asset, whether it exists or not
  • Plugin registers a blank asset with the same name to override it
  • Works even if the asset doesn't load during your test

When to use:

  • The asset loads conditionally (only on certain page types)
  • You want guaranteed removal regardless of page context
  • You're a power user who knows the asset registration names

Example:

File: media/system/js/core.js
Asset: core

How to find asset names:

  • Check extension source code
  • Use browser DevTools to inspect script tag attributes with debug enabled
  • Look in extension's joomla.asset.json file
  • Ask the extension developer

Combining Both Methods

You can (and often should) specify both:

File: media/system/js/core.js
Asset: core

This provides:

  • The file path for bundling (what to include)
  • The asset name for guaranteed removal (what to disable)

If you specify ONLY the asset name without a file path, the plugin will try to remove it but won't know what to bundle. This will cause errors. Always specify the file path.


Configuration Walkthrough

Bundle Settings

Bundle Name

Required
A unique identifier for this bundle.

Examples:

  • scripts-main
  • scripts-defer
  • styles-global
  • bootstrap-components

Rules:

  • Use lowercase
  • No spaces (use hyphens)
  • Must be unique across all your bundles

Type

Required
Choose JavaScript or CSS.

Important: JavaScript and CSS must be in separate bundles. You cannot mix them.

Attributes (JavaScript only)

Optional
Controls how the bundled script executes.

Options:

  • None - Normal blocking script (executes immediately)
  • defer - Executes after HTML parsing completes
  • async - Executes as soon as it's downloaded
  • Both - Browser chooses best strategy

CRITICAL RULE: Scripts with different attributes MUST be in separate bundles.

Why? If you bundle a deferred script with a normal script, both will use the bundle's attributes, potentially breaking execution order.

Example - WRONG:

Bundle: scripts-main
Attributes: (none)
Files:
  - media/system/js/core.js (normally loaded with defer)
  - media/vendor/bootstrap/js/bootstrap.js (normally loaded without defer)

This will force core.js to execute immediately instead of being deferred, potentially breaking things.

Example - CORRECT:

Bundle: scripts-normal
Attributes: (none)
Files:
  - media/vendor/bootstrap/js/bootstrap.js

Bundle: scripts-defer  
Attributes: defer
Files:
  - media/system/js/core.js

File Settings

File (Required)

The file path/URI of the asset to bundle.

Format:

  • Can start with or without leading slash
  • Relative to site root
  • Do NOT include domain or protocol

Valid:

media/system/js/core.js
/media/system/js/core.js
templates/cassiopeia/js/template.js

Invalid:

https://yoursite.com/media/system/js/core.js
../media/system/js/core.js

Asset (Optional)

The WebAssetManager registration name for this asset.

When to use:

  • You know the exact asset name
  • The asset loads conditionally
  • You want guaranteed removal

How to find it: Most assets follow patterns:

  • Core: core.{name} (e.g., core.core-js)
  • Components: com_{component}.{name}
  • Plugins: plg_{group}_{element}.{name}
  • Templates: template.{template}.{name}

Check the extension's joomla.asset.json file or source code for exact names.


Finding Asset Information

Finding File Paths (Easy - Debug Required)

Method 1: Browser DevTools

  1. Open your site in browser
  2. Press F12 to open DevTools
  3. Go to Network tab
  4. Check Disable cache
  5. Reload the page
  6. Look for .js and .css files in the list
  7. Copy the path from the Name column

Example:

Name: media/system/js/core.js
Status: 200
Type: script

Use media/system/js/core.js as your file path.

Method 2: View Page Source

  1. Right-click page → View Page Source (Ctrl+U / Cmd+U)
  2. Search for <script or <link rel="stylesheet"
  3. Find the src/href attributes
  4. Copy everything after your domain

Example HTML (without debug):

html
<script src="/media/system/js/core.js" defer></script>

Use media/system/js/core.js as your file path.
Note the defer attribute - you'll need this for bundle configuration.

Finding Asset Names (Advanced)

Asset names are how Joomla's WebAssetManager internally identifies registered scripts and styles. You have two approaches:

Easy Way: Enable debug mode temporarily (5 minutes of work)
Long Way: Dig through PHP code and JSON files (30+ minutes of work)

Most users should use debug mode. The long way is only necessary if you can't enable debug on a production site.

Method 1: Enable Joomla Debug Mode (Easy - Recommended)

Enable debug:

System → Global Configuration → System → Debug System: Yes

Then view page source:

With debug enabled, Joomla adds data-asset-name attributes to script and link tags:

Example HTML (with debug enabled):

html
<script src="/media/system/js/core.js" defer data-asset-name="core"></script>

The data-asset-name value is what you need: core

Steps:

  1. System → Global Configuration → System → Debug System: Yes
  2. Save and close
  3. Load your site's frontend
  4. Right-click → View Page Source (Ctrl+U / Cmd+U)
  5. Search for the script/style file path you want to bundle
  6. Look for data-asset-name="..." in that tag
  7. Copy the asset name value
  8. Go back and turn debug mode off (for security/performance)

Why this is easy: 5 minutes, no file editing, no code reading, just copy/paste.

Method 2: Check joomla.asset.json Files (Long Way)

If you can't enable debug mode (production site, no access to config, etc.), you can find asset names by reading the extension's asset definition files.

Common locations:

/media/system/joomla.asset.json           (Joomla core)
/media/com_{component}/joomla.asset.json  (Components)
/media/plg_{group}_{plugin}/joomla.asset.json (Plugins)
/media/templates/site/{template}/joomla.asset.json (Templates)
/media/mod_{module}/joomla.asset.json (Modules)

Example from template's joomla.asset.json:

json
{
  "$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json",
  "name": "template.cassiopeia",
  "version": "4.0.0",
  "assets": [
    {
      "name": "template.cassiopeia.user",
      "type": "script",
      "uri": "templates/cassiopeia/js/user.js",
      "attributes": {
        "defer": true
      }
    }
  ]
}

From this you learn:

  • Asset name: template.cassiopeia.user
  • File path: templates/cassiopeia/js/user.js
  • Attributes: defer

Steps:

  1. Identify which extension loads the asset (from file path in Network tab)
  2. Navigate to that extension's media folder on your server (FTP/file manager)
  3. Look for joomla.asset.json
  4. Open the file and find the asset definition with matching uri
  5. Copy the name value

Why this is long: Have to identify the extension, navigate file system, open JSON files, search through them. Repeat for every asset.

Method 3: Search Extension PHP Code (Long Way - Last Resort)

Some extensions register assets in PHP code instead of JSON files.

Look for these method calls:

php
$wa->registerScript('asset-name', 'path/to/file.js');
$wa->registerAndUseScript('asset-name', 'path/to/file.js');
$wa->registerStyle('asset-name', 'path/to/file.css');
$wa->registerAndUseStyle('asset-name', 'path/to/file.css');

The first argument is the asset name.

Common file locations:

/plugins/{group}/{plugin}/src/Extension/{Plugin}.php
/components/com_{component}/src/View/{View}/{Format}.php
/templates/{template}/index.php
/templates/{template}/html/{component}/{view}/default.php
/modules/mod_{module}/mod_{module}.php

Example from a plugin:

php
$wa = $doc->getWebAssetManager();
$wa->registerAndUseScript(
    'plg_system_myplugin.main',           // ← This is the asset name
    'media/plg_system_myplugin/js/main.js',
    [],
    ['defer' => true]
);

Asset name: plg_system_myplugin.main

Steps:

  1. Identify which extension loads the asset (from file path)
  2. Download or access extension files (FTP/file manager)
  3. Search ALL PHP files for registerScript, registerAndUseScript, registerStyle, or registerAndUseStyle
  4. Find the call where the second argument matches your file path
  5. Copy the first argument (the asset name)

Why this is last resort: Have to download files, search through code, understand PHP. Very time-consuming.

Realistic Expectations:

You'll probably encounter a mix of both.  Some will be in json, some in PHP.  In some templates, the assets are registered via a variable - so you'll need to search for registerAndUseScript/registerAndUseStylesheet and interpret the code to figure out what the asset name is. There is not really any method to do this automatically - but it only needs to be done once per asset.

Quick Reference: Which Method When

For File Paths (Always Easy):

  • DevTools Network tab → See all loaded files, copy paths ✅
  • View Page Source → See attributes (defer/async), verify paths ✅

For Asset Names (Choose Your Path):

  • Debug Mode → EASY: 5 minutes, just enable and copy from page source ✅✅✅
  • joomla.asset.json → LONG: 30+ min, navigate files, search JSON ⏱️
  • PHP Code Search → LONGEST: Download files, grep code, understand PHP ⏱️⏱️

Recommendation: Just enable debug mode for 5 minutes. Seriously. It's so much easier than the alternatives.

WARNING: Do NOT guess asset names based on patterns. Wrong names mean the asset won't be removed, bundles won't work correctly, and you'll waste time troubleshooting. Always verify using one of the methods above.


Best Practices

Start Small

Begin with 2-3 obviously site-wide files. Test thoroughly. Add more gradually.

Group by Attributes

Create separate bundles for normal, deferred, and async scripts:

  • scripts-normal (no attributes)
  • scripts-defer (defer only)
  • scripts-async (async only)

Test Across Page Types

After configuration, visit:

  • Homepage
  • Article pages
  • Category pages
  • Contact forms
  • Any page type your site uses

Ensure everything still works. If something breaks, that asset probably wasn't site-wide.

Use Asset Names for Certainty

If you know the asset name, specify it. This ensures removal even if the asset doesn't load during your test page.

Document Your Configuration

Keep notes about what you bundled and why. Future you (or another admin) will thank you.

Monitor After Updates

When you update extensions, check if they:

  • Changed file paths
  • Added new assets
  • Removed old assets

Bundles rebuild automatically, but you may need to update your configuration.  The media_version cache item will need to be cleared after each update if you've enabled any kind of client-side cache. System > Cache > find media_version, clear it.


Troubleshooting

Bundle File is Empty or Tiny

Problem: Generated bundle is 0KB or very small

Causes:

  1. File paths are incorrect
  2. Files don't exist at specified paths
  3. Permissions prevent reading files

Solution:

  • Verify file paths in DevTools Network tab
  • Check files exist on server
  • Enable Joomla debug mode and check error logs
  • Look for "System - Bundler could not add file" messages

Assets Still Loading Individually

Problem: Original files still appear in page source

Causes:

  1. Asset name specified but doesn't match actual name
  2. Asset added via deprecated methods ($doc->addScript())
  3. Template renders scripts directly in PHP
  4. Asset loads after plugin runs

Solution:

  • Verify asset name is correct
  • Check if extension uses WebAssetManager
  • Try specifying both file path AND asset name
  • Check if template uses deprecated methods

JavaScript Errors After Bundling

Problem: Console shows errors after enabling bundles

Causes:

  1. Scripts bundled with wrong attributes
  2. Execution order changed
  3. Dependencies broken
  4. Mixed site-wide and page-specific scripts

Solution:

  • Check bundle attributes match original scripts
  • Ensure defer/async scripts are in separate bundles
  • Verify all bundled scripts are truly site-wide
  • Temporarily disable bundle to confirm it's the cause

Bundles Not Updating After Changes

Problem: Made config changes but bundles still show old content

Causes:

  1. Browser cache
  2. Joomla cache
  3. CDN/reverse proxy cache

Solution:

  1. Clear Joomla cache (System → Clear Cache)
  2. Hard refresh browser (Ctrl+Shift+R / Cmd+Shift+R)
  3. Clear CDN cache if using one
  4. Check file timestamp on server

Template Assets Not Bundled

Problem: Template's JavaScript/CSS still loading separately

Causes:

  1. Template uses deprecated $doc->addScript() methods
  2. Template renders scripts directly in HTML
  3. Asset name not specified

Solution:

  • Specify the asset name explicitly
  • Check template code for deprecated methods
  • Contact template developer about WebAssetManager support

Advanced Usage

Multiple Bundles Strategy

Create bundles based on asset characteristics:

By Load Timing:

Bundle: scripts-blocking
Attributes: (none)
Files: Critical scripts that must load first

Bundle: scripts-defer
Attributes: defer  
Files: Enhancement scripts that can wait

Bundle: scripts-async
Attributes: async
Files: Independent scripts (analytics, etc.)

By Framework:

Bundle: bootstrap-components
Type: JavaScript
Files: All Bootstrap JS components

Bundle: bootstrap-styles
Type: CSS
Files: Bootstrap CSS files

Conditional Asset Strategy

For assets that load on MOST but not ALL pages:

  1. Use asset name for guaranteed removal
  2. Accept that it bundles into all pages
  3. Weigh the tradeoff: Extra KB on pages that don't need it vs. complexity of multiple bundles

Example: If an asset loads on 90% of pages, bundling it everywhere is probably fine. The cache benefit outweighs the small overhead on the 10% of pages.

Debugging Mode

Enable Joomla debug mode to see detailed error logs:

configuration.php:

php
public $debug = 1;
public $error_reporting = 'maximum';

Check administrator/logs/ for Bundler messages.

Manual Bundle Regeneration

To force bundles to regenerate:

  1. Go to plugin settings
  2. Make any change (even trivial)
  3. Save

This clears cache and triggers full rebuild.


Limitations

What Can Be Bundled

Supported:

  • Assets registered via WebAssetManager
  • Template files using WebAssetManager
  • Plugin/module/component assets using WebAssetManager
  • Any properly registered JavaScript or CSS

Not Supported:

  • ES6 modules (type="module")
  • Assets using deprecated $doc->addScript() / $doc->addStyleSheet()
  • Inline scripts or styles
  • Directly rendered HTML in templates
  • External/CDN-hosted files

Note: CDN-hosted files doesn't mean that you can't use a CDN for YOUR files.  If you're using someone else's CDN hosted files, this won't help you.

Deprecated API Note

$doc->addScript() and $doc->addStyleSheet() are deprecated in Joomla 4+ and will be removed in Joomla 7.

If an extension still uses these methods:

  1. It won't work with Bundler
  2. It will break in Joomla 7
  3. Contact the developer about updating to WebAssetManager

Bundler only supports modern, future-proof APIs.

Site-Wide Assets Only

You must only bundle assets that load on EVERY page.

Bundling page-specific assets causes:

  • Unnecessary code on pages that don't need it
  • Larger initial download
  • Wasted bandwidth
  • Potential functionality issues

When in doubt, don't bundle it.

Why is this software free?

I’m ditching the freemium game and giving this software to the Joomla crowd for free. It’s a nod to “Jumla”—Swahili for “all together”—because fragmentation sucks, and I’d rather focus on innovation and paid gigs. Use it, build with it, and if you need custom work, I’m super into that.

What's The Catch?

There isn’t one! I’m all about building tools that empower the Joomla community and spark creativity. This software’s free because I’d rather see it in your hands - fueling awesome projects. If you really feel like paying something, I’d appreciate a review in the Joomla Extension Directory—your feedback means a lot!