Photo by Nigel Tadyanehondo on Unsplash

Today I got sidetracked by an article trying to answer a simple Joomla! question, and the incredibly wrong direction it took the answer to. I ended up writing the not-so-straightforward code to answer the question correctly, and had a lot of reflection on how changing, or omitting, the context of a question can be problematic.

The question

I have a site built with Joomla! 4 or 5. I have created and use a child template of Cassiopeia. How can I tell it to stop loading FontAwesome without having to fork the entire Cassiopeia template?

On the face of it, this is a simple request.

We can infer that we are talking with a moderately technical user who feel confident enough to create their own custom template as a child template of Joomla's default Cassiopeia template – a strongly recommended approach which I am also following for this very site – but not technical enough to understand how Joomla's WebAssetManager works and how to work around it.

I can see your eyes glazing over, so let's backtrack a bit.

Joomla!, and third party libraries: the past

Back in the olden days of Joomla! versions 1.0 to 2.5, if a third party extension developer (usually called a "3PD") needed to include a third party CSS library such as, say, FontAwesome they had to bundle it with their extension. Since Joomla! did not have any kind of dependency management, each extension would be unaware if there was another extension by the same or a different vendor loading the same third party dependency. As a result, you ended up with multiple copies of the same stuff loaded on a single page of the site.

This was problematic for two reasons. First of all, size and computational effort were unnecessarily high. In layman's terms, the site was dog slow. Second, and equally important, there was no guarantee that each module, component, and plugin wouldn't load a slightly different version of each dependency, causing functional issues. In other words, stuff looked broken.

Joomla!, and third party libraries: the present

Joomla! 4 addressed this situation with an one-two punch. Instead of having 3PDs load random CSS and JavaScript all over the place, it introduced the WebAssetManager. That's a simple mechanism which can track dependencies between files. For example, as a 3PD I can say that my component's backend CSS depends on Bootstrap and FontAwesome, while my frontend CSS has no dependencies because I'm freaking cool and provide my own CSS. Not exactly a novel idea. It's something that WordPress has had for well over a decade, and it's proven to solve a lot of problems.

The second part of the one-two punch was the fact that Joomla! ships with common libraries which were being used by many 3PDs: Bootstrap, FontAwesome, TinyMCE, Choices.js, etc. All I have to do as a 3PD is create a special file in my extension's media folder subdirectory called joomla.asset.json and set up my static resources and their dependencies. Then, I can load them up through WebAssetManager in my software and let Joomla! figure out how and when exactly this should happen. That's blessed magic, as I've already discussed in my book.

Why does Cassiopeia depend on FontAwesome?

If you dissect the joomla.asset.json file of Joomla's default template, Cassiopeia, you will see this little nugget:

    {
      "name": "template.cassiopeia.ltr",
      "description": "The css file to be used when the site is left to right (LTR).",
      "type": "style",
      "uri": "template.min.css",
      "dependencies": [
        "fontawesome"
      ]
    },
    {
      "name": "template.cassiopeia.rtl",
      "description": "The css file to be used when the site is right to left (RTL).",
      "type": "style",
      "uri": "template-rtl.min.css",
      "dependencies": [
        "fontawesome"
      ]
    },

... more lines ...

    {
   "name": "fontawesome",
   "type": "style",
   "uri": "system/joomla-fontawesome.min.css"
  }

At first blush, it looks really weird that Cassiopeia's main CSS file depends on FontAwesome, and that the FontAwesome dependency is also provided in the same file. What gives?

The answer is annoyingly banal: convenience.

A lot of Joomla's built-in modules and components use iconography instead of just text. This is a deliberate choice. Iconography is parsed faster in our brain than a wall of text, if used in the right amount. As I am writing this article I am looking at an editor toolbar which consists entirely of icons. I can find everything at a glance, literally. If I had long labels of text such as Bold, Italics, Underline, Strikethrough, Align Left, Align Right etc I would be far less productive.

Sidebar: Back in the early 90s our screens were teensy tiny; 12.5 inches visible space, 4:3 aspect ratio, 640x480 pixels at best. Using Word on Windows 3.1 and 95 didn't give us a lot of space for a toolbar. There was no Ribbon interface; that came in 2006. We had to memorise shortcut keys for our most common formatting commands instead of going through endless text-only menus (menus only got icons in Windows 95, but it took three more years for Microsoft Office to use them). So, yes, do believe me when I say that iconography, when used correctly, can increase your productivity – unless you're willing to put the effort into memorising keytrokes. F7 for spell check, anyone? It's nearly 25 years later and I still remember it!

Iconography rocks. But remembering to do something like \Joomla\CMS\Factory::getApplication()->getDocument()->getWebAssetManager()->useStyle('fontawesome'); on every single view template which needs to display icons is very repetitive and, as such, error-prone. Hence Cassiopeia putting FontAwesome  as a dependency of the main CSS file, ensuring it will be loaded.

So, what's wrong with that?

If you ask me, absolutely nothing! As I said, I love iconography. It can help focus your eyes and makes the page feel less of a wall of text, much more than adding tons of whitespace does.

It does come at a marginal cost, though. You get to load 178 KiB. Once only; the first time you visit the site. This has a negligible impact on your page load speed, unless you are talking about a really slow connection, with lots of latency.

In all seriousness now, you may have noticed that 3G networks have been shut down, and the calendar reads 2024. The worst conditions you will find in the real world is a 4G connection with a bottom of the barrel $50 Android phone. Which is to say, Lighthouse tests are unrealistic unless your target audience is in a ship in the middle of the Atlantic, in a storm, using a desktop from the early 00s. Everyone else will barely see a 3% to 5% performance impact loading FontAwesome, while greatly improving their comprehension of the page.

But for the sake of argument let's say that the person asking the question has a valid reason. They are making a site for the blind, or for poor students trying to do their homework off the free WiFi in a McDonald's parking lot, or they need to load a completely different iconography set which best suits their needs. Either way, we accept their premise as valid and get on with it.

Bad answers: the plight of LLMs ("AI")

The "modern" approach to getting coding questions answered is, apparently, to ask the village idiot a large language model, commonly and wrongly called an "AI", for its incoherent hallucinations enlightening answers.

First of all, let's not call them "AI" (Artificial Intelligence). There's no intelligence in LLMs. They are big statistical models with billions of parameters. They take your input prompt and produce words which are statistically more likely to go together in correlation with that input prompt. They have no understanding of what you ask them, they don't "know" anything, they have no comprehension. As a result, the answers they come up with are very often unusable nonsense.

I decided to use Microsoft Copilot because, unlike other LLMs, it actually uses search results to find information that is more relevant to the query and tries to sum it up in a semi-coherent output. Of course the age-old rule of computing, SISO (shit in, shit out) still applies, but at least it has the decency of giving me its sources so I can evaluate its answers using my non-artificial and very real intelligence.

Given the above query, we got... something.

It told me to put the following code into my template's index.php file, before loading Cassiopeia's index.php itself:

$wa = $this->getWebAssetManager();
$wa->disableAsset('style', 'fontawesome');

This is nonsense. It doesn't even work. I'll come back to that. At least, Copilot gave us a good pointer to look further: https://github.com/joomla/joomla-cms/issues/38898

Bad answers: regurgitated content out of context

For our next contestant, we have an article written by someone who should have known better. A web professional specialising in Joomla who has served in an executive position in Joomla itself. He wrote an article which suggested the following without any qualification on its use:

$wa = $this->getWebAssetManager();
$wa->registerStyle('fontawesome', '');

This is better, in the sense that it works. It is lifted from the very familiar-looking https://github.com/joomla/joomla-cms/issues/38898 issue on GitHub. Yup. That's the same one Copilot spewed out. Given the article's author's outspoken advocacy for LLMs I think I know where he got the idea.

Unfortunately, that author did not understand the context of that GitHub issue, nor the ramifications of using it without understanding how Joomla! works, and how that (deliberately!) breaks Joomla. When I told him he's breaking Joomla with his bad advice he got... salty.

All right! Let' get down to why both answers are bad, and then the right way to do it.

Debunked: disableAsset

This only works for top level assets, not dependencies.

Moreover, at the point the LLM told us to do that, before the template loads its assets, the dependency is not even loaded in the WebAssetManager, so there's sod all to disable.

The LLM hallucinated a solution which doesn't work, which is surprising given the source material it quoted. LOL!

Debunked: registerStyle

It's not wrong, it's wrong when proposed without any context.

When Joomla's co-founder Brian Teeman asked that question on GitHub the unspoken, but well-understood for all of us paying attention and knowing Brian context was that he was trying to create a completely custom template which does not, in fact, use any iconography. In that context, the answer on GitHub is valid. It does nuke FontAwesome from high orbit, and it does it very well. This is where the problem lies.

Instead of removing the FontAwesome dependency from Cassiopeia, it tells Joomla to load nothing when it is told to load the fontawesome dependency. The difference is that between taking someone's keys, and erecting a brick wall in the place of the door. If any other extension tries to use FontAwesome, it won't work. There's nothing to load.

When this kind of advice appears outside the context it was originally given, it's dangerous. The person who implements it doesn't know about WebAssetManager, does not understand why a change in the template would affect a component, module, or plugin and will be caught off-guard when a third party component, module, or plugin does not display icons. Their immediate reaction will be to assume it's a bug in the third party code, badger its developer, who will waste a lot of time to see that nope, FontAwesome isn't loaded, and have to waste even more time explaining to the user that they did something stupid, and why it's stupid.

This is unnecessary tension. It can be avoided by just putting a simple notice: "Warning: Doing this will make icons in most third party extensions to disappear. It's not a bug in those extensions. If it happens to you and you don't like it, undo this change". But, no, people writing bad articles don't care about corrections, so here we are.

What's even worse is that if a 3PD gets fed up with this they will go back to doing what they were doing in the olden days: ship FontAwesome with each of their extensions using those icons. Therefore, you will have multiple copies of FontAwesome loaded on a page. Instead of saving 178 KiB you will end up loading that several times over. Instead of these "simple tricks" making your site faster, they will end up making all sites slower.

I have seen idiotic "tricks" like that all over the place. Idiots telling people to disable the API application even though it's not actually needed is a top pet peeve of mine, given that I maintain Panopticon which does use the API application. And yes, I have seen the stupid thing about FontAwesome in the wild as well, more than once. At least my extensions don't convey context solely by using icons, but it's still annoying when people blame me for what some other fool told them to do without warning them of the consequences.

The "right" way to do it

There are many ways to skin the proverbial cat.

One option would be creating a joomla.asset.json for our child template, removing the FontAwesome dependency, and forking index.php and error.php from Cassiopeia to point them to our template, not Cassiopeia, as the source of the joomla.asset.json file to load. This works, but it requires maintenance with each new minor version of Joomla (5.0 to 5.1 to 5.2 etc). Not necessarily a bad thing, but not "magical" either.

Another option is to add some code at the bottom of our index.php (after including Cassiopeia's index.php) and use PHP Reflection to edit the loaded main Cassiopeia CSS asset, removing the dependency to FontAwesome. This is the best solution, but the use of Reflection is a bit icky and I avoid it if I can help it. The reason is that it depends on my magic knowledge of how the code's deliberately inaccessible parts are named and used. Any change in Joomla! itself will break this solution in a spectacular fashion (site crash).

This leaves me with the third option I could think of. More verbose, but more robust. We can attach event handlers (formerly known as "plugin handlers") to Joomla's application outside a plugin, whenever we want. We can trap the events Joomla sends before rendering the page, and after it's rendered each module. If there is no dependency on FontAwesome except for Cassiopeia, use the registerStyle method to remove FontAwesome. If it's used, however, we will restore the asset to its previous state.

Yes, I said restore, because Joomla will be calling our event handler many times, before we have a final picture of asset dependencies. So, instead of just using registerStyle to nuke FontAwesome, we actually save a copy of that dependency, so if we end up needing it we can simply register it all over again.

It's about as simple as breakdancing on a tightrope with your eyes tied behind your back, but if you really need it here it is: https://github.com/nikosdion/notawesome/blob/main/templates/site/tpl_notawesome/index.php 

Of course, if you know that 100% you will NOT need FontAwesome, and neither will any third party extensions (or just don't care) you can simply do:

$wa = $this->getWebAssetManager();
$wa->registerStyle('fontawesome', '');

So, yes, that solution is valid AS LONG AS you understand the implications and are okay with them. Otherwise, use the more convoluted code I gave you and it will work 99.8% of the time.

Can we stop giving people bad advice?

I am not talking about LLMs; they give bad advice by default. It's their nature, and I mean it in the mathematical sense. No matter what you do, they will always produce hallucinations (that's the technical term!). If you have anything that's more critical than having a good laugh, don't trust an LLM.

I am talking about us. Actual people. People with experience, writing articles. People who other folks consider "experts".

If we keep telling people "do X" without explaining what it does, why it solves a problem, and what second and third order problems it will create we are being irresponsible idiots. People will follow our advice blindly because, surely, we wouldn't tell them to do the Joomla! equivalent of jumping off a high building just because we just happen to have a parachute they don't and about which we never talked about, right? RIGHT?!

Qualifying your advice does not make you appear less professional. Giving unqualified advice which will cause problems does.

So, here you have it. A simple question, we started with, and it was anything but simple. What a wild ride it's been!

Until next time.

4 comments

  • I think there may be another area to investigate.

    Note that I have not checked this myself or even asked randomGPT and I am probably opening myself up to a long reply pointing out that I have misunderstood something obvious. But I am feeling brave so here goes.

    If you look at the Joomla 5 behaviour - compat plugin you will see an option "Removed Assets"

    From the description we can see the intention of this option is to

    Activate this option if your extension requires removed assets which has resulted in an exception. The assets provided are empty but prevent the exception

    The code block for this points you to removed.asset.json

    I will let you, dear reader, follow the trail of clues and see what you can come up with. While it won't lead you to a perfect solution it will show you what to do to prevent future errors with 3pd extensions that are trying to load an asset you have removed and as a result spits out an ugly error and who knows maybe you can build upon this approach.

    • The problem I explorde here is that the fontawesome asset does exist, but it's empty, so it does nothing. There is no visible error to provide a clue. Everything works, but icons don't appear, so the user thinks it is a bug with the extension when it is in fact a problem with the template.

      The plugin you mention solves the mirror opposite problem: someone removed the fontawesome asset altogether from the joomla.asset.json of the template. In this case the extension tries to load fontawesome, but since the asset doesn't exist Joomla throws an exception which results in a visible stop error. If the user did not intend that to happen, they fix their template. If they really did intend the fontawesome dependency to go away... what do they do?

      That's where this plugin comes in. So what the plugin does is what the template in our example did: create the fontawesome asset, but have it blank. The visible error goes away, but still icons don't appear, which is presumably what the user wanted.

      At least that is my understanding from having very briefly looked at the plugin. It's 11:30pm here, so any further toying around would have to wait for the weekend.

  • yes it was late and i probably shouldnt have replied without reading more clearly.

    I dont actually see anything majorly wrong with the blog posts suggested method. I cant disagree with it as I have done it myself for a demo.

    Your comment about extensions who might be relying on the asset is perfectly valid though and setting a dummy empty asset will clearly cause problems - and I think the blog post does indicate that but probably without sufficient warning.

    I did a quick google and saw a few template frameworks doing much much worse with fontawesome. 

    I suspect that the best solution to the valid issue is to only declare fontaweome as an asset in its own right and not as a dependency. That way if the template doesnt call it the extension will still be able to do so. WebAssetManager is a great and powerful addition to Joomla but its not obvious (or documented well enough) how to truly use it.

    • I did explain the problem a bit, and it becomes obvious when you use something like the sample module I have in https://github.com/nikosdion/notawesome. There are no errors to give you an indication that something's wrong, but no icons appear.

      The first time I saw a problem like that (on a commercial template) was because a user was complaining that ATS was broken for not displaying icons in the frontend. We checked the template and saw that indeed FontAwesome is not being loaded at all. Explained that to the client, wasting a lot of time, for what is ultimately a tertiary issue at best (as I said, we don't convey any critical information or context solely by using icons; they are visual aids, not the only visible marker).

      And yes, some templates do unspeakable things. I have seen a template which loads FontAwesome. Not the one included with Joomla. A partial build they supplied, with a modified CSS to make icons... about 50% bigger.

      In the end of the day, if I have an extension that relies on iconography I will have to end up creating my own, privately namemespaced FontAwesome distribution and include it with my software just because anything else is bad for business. Yes, of course this creates the insurmountable problem for all users that they get to choose between their site getting bogged down from me loading ~200KiB, or put the onus on them to create template overrides for each and every view template, and keep them up to date with each and every version.

      In other words, we are back to Joomla! 1.5's wild west. 15 years of progress down the drain. Just because Joomla sucks at enforcing its advancements, and template developers do stupid shit because they can't be arsed to understand WHY Joomla does things in a certain way. That's what I am trying to raise awareness for.