No Code Attached Yet
avatar PepeLopez
PepeLopez
11 May 2022

Definition of the problem

If the frontend is a template, which does not use any kind of the default template (like bootstrap or as the title says the core.min.js), it's not possible to remove the core.min.js file from <head> part of the document.

To dig a bit deeper, let's explain what's happening.

In the template main index.php we have
<jdoc:include type="head" />

This is pretty necessary for any system plugin, which is (trying) to modify the <head> section, e.g. the SEF plugin.
Let's take the SEF plugin as reference. It "simply" adds the canonical link tag like this

<link href="https://my.site/path/to/article" rel="canonical">

This is achieved by this line in sef.php (line 79):
$doc->addHeadLink(htmlspecialchars($canonical), 'canonical');

If <jdoc:include type="head" /> is NOT present in template, the modification will NOT appear

So let's conclude, that modifications via $doc
$doc = $this->app->getDocument();

are only possible, if <jdoc:include type="head" /> is present in template.

Now, let's try to just get rid of core.min.js - it's possible in any (system) plugin with onBeforeCompileHead() like that:
$wa = $doc->getWebAssetManager(); $wa->getRegistry()->remove("script", "core");

But wait - this error pops up then:

Joomla\CMS\WebAsset\Exception
UnsatisfiedDependencyException
Unsatisfied dependency "core" for an asset "joomla.script.options" of type "script"

So, let's try to get rid of that dependency with

$wa->disableAsset("script", "joomla.script.options");

But it comes this error

There is no "joomla.script.options" asset of a "script" type in the registry.

So joomla.script.options needs core.min.js - but it's not accessible at the very last possibility (thats onBeforeCompileHead()) to remove??

So I digged even deeper and found this FAIL in MetasRenderer.php (starting at line 60):

 // Trigger the onBeforeCompileHead event
		$app->triggerEvent('onBeforeCompileHead'); // Fail 1: Too early

		// Add Script Options as inline asset
		$scriptOptions = $this->_doc->getScriptOptions();

		if ($scriptOptions)
		{
			$prettyPrint = (JDEBUG && \defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : false);
			$jsonOptions = json_encode($scriptOptions, $prettyPrint);
			$jsonOptions = $jsonOptions ?: '{}';

            
            $wa->addInlineScript(       // Fail 2: After onBeforeCompileHead - so it's not accessible to change!
                $jsonOptions,
                ['name' => 'joomla.script.options', 'position' => 'before'],
                ['type' => 'application/json', 'class' => 'joomla-script-options new'],
                ['core']
            );
	}


What the fück is this fail?

Why are you injecting joomla.script.options AFTER triggering onBeforeCompileHead() ??
There is NO reason to do that!
In fact, that leads to the problem, that it's not removable for the frontend, where it's not necessary when using custom templates!

Important note:
joomla.script.options is necessary for the backend - fine so far. But actually it's hard coded in the system, it's not possible to get rid of it for the frontend, where it's maybe not necessary!

Possible solutions

Solution 1

As I wrote before, I see no need to do it THAT way in MetasRenderer.php - maybe there is a reason I don't know, however, it IS needed in backend (with default template) for sure, so why not enclose it like this:

 if ($app->isClient('administrator')
            ) {
                $wa->addInlineScript(
                    $jsonOptions,
                    ['name' => 'joomla.script.options', 'position' => 'before'],
                    ['type' => 'application/json', 'class' => 'joomla-script-options new'],
                    ['core']
                );
            }

With this solution, it's available in backend as needed, but not in frontend.
If it's necessary in frontend, you can handle it somewhere else (in plugins, templates,...) - and so it would become removable in frontend if necessary.

Solution 2

Just put it before the onBeforeCompileHead() trigger.
I mean, why not!? Why is it dependend on the fact if $scriptOptions is set or not? Just put it in, because it seems to be necessary in backend anyway.
And $scriptOptions seems to be filled always - so the if() statement seems superfluous.

Additional comments

If you ask yourself, why this is a deal, there are 2 points:

1st: That include is "hard coded" in system files, and this special part is truely not required in frontend with custom templates. If there is a need for that, it should be coded in the (default) template or somewhere else, but NOT in the MetasRenderer.php !

2nd: When it comes to SEO, page speed is king! Just eliminate every unnecessary http request, this is what every optimization guide will tell you!
So, even with a blank custom template and a fresh installed Joomla4.x, there will be the core.min.js and the bootstrap.es5.min.js - even if you need it or not. It's possible to get rid of the bootstrap js file in a system plugin like this:

$wa = $doc->getWebAssetManager();
        $wa->disableAsset("script", "bootstrap.collapse");
        $wa->getRegistry()->remove("asset", "bootstrap.collapse");
        $wa->getRegistry()->remove("asset", "bootstrap.es5");

However, it's not possible with the core.min.js file, so that's why I urgently ask to change that as described above!

avatar PepeLopez PepeLopez - open - 11 May 2022
avatar joomla-cms-bot joomla-cms-bot - change - 11 May 2022
Labels Added: No Code Attached Yet
avatar joomla-cms-bot joomla-cms-bot - labeled - 11 May 2022
avatar dgrammatiko
dgrammatiko - comment - 11 May 2022

You're wrong, core is NOT forced in the templates. Here is the reason why you have core.js in the front end:

The messages load the script: messages

->useScript('messages');

That script has a dependancy on core.js:

"name": "messages-legacy",
"type": "script",
"uri": "system/messages-es5.min.js",
"attributes": {
"nomodule": true,
"defer": true
},
"dependencies": [
"core"
]
},
{
"name": "messages",
"type": "script",
"uri": "system/messages.min.js",
"attributes": {
"type": "module"
},
"dependencies": [
"messages-legacy"
]
},

In short, if you want to remove the core.js you need to come up with your own script for system messages. All the rest that you wrote is not correct...

avatar brianteeman
brianteeman - comment - 11 May 2022

2nd: When it comes to SEO, page speed is king! Just eliminate every unnecessary http request, this is what every optimization guide will tell you!

If you mean every outdated guide then yes you are correct

avatar PepeLopez
PepeLopez - comment - 11 May 2022

I'm sorry, you did not read or even tried to replicate the problem.

It's NOT triggered by message.php.
Just for the sake, I created an override for message.php and return; in the first line, and the error I described above is still there!! Your answer is bogus!

As I wrote exactly, the error message clearly says

Unsatisfied dependency "core" for an asset "joomla.script.options" of type "script"

How can I make this more clear for you?

And it comes from the exact point where I pointed to.

Please read carefully and even TRY to replicate the problem:

  • Fresh J4
  • "Blank" template (with <jdoc:include type="head" /> )
avatar dgrammatiko
dgrammatiko - comment - 11 May 2022

"Blank" template (with <jdoc:include type="head" /> )

Can you paste your index.php of your Blank template?
Also are there any modules?
What is the component that renders the page that you're talking about?

In short you think that your reasoning is correct but probably you're missing the point:

  • The CMS is NOT imposing the core.js
  • The core.js is a common dependency for many other scripts
avatar Fedik Fedik - change - 11 May 2022
Status New Closed
Closed_Date 0000-00-00 00:00:00 2022-05-11 17:34:14
Closed_By Fedik
avatar Fedik Fedik - close - 11 May 2022
avatar Fedik
Fedik - comment - 11 May 2022

I see you have made a huge analysis.
Sorry to disappoint you, you made incorrect conclusion.

If you look in MetasRendered you may notice a litle IF: if ($scriptOptions),
Which means that some code have added the script options and this is require core.js.

In general it possible to disable any asset as long as another asset does not depend from it.
So, to disable "core" asset you have to disable all assets that depend from it.

Addittionaly:
You should never remove anything from Registry $wa->getRegistry()->remove("script", "core");, It will easily break your site. Use $wa->disableScript('core'); instead

I am closing this, because it not an issue.

Add a Comment

Login with GitHub to post a comment