I want to display some of the styles and scripts using rel='preload' to make my pages load faster - referring to the Google Lighthouse.

<link rel="preload" href="style.css" as="style">
<link rel="preload" href="main.js" as="script">

Is there any way to do this using addScript/addStyleSheet in Joomla?

$document->addStyleSheet("css/style.css");
$document->addScript("js/us.script.js");
up vote 3 down vote accepted

I'll answer this myself too as I have a lot of experience with lazy loading assets.

preload may seem like it asynchronously loads files but it doesn't. They're still considered render blocking.

This also applies if you also just add your assets to below the closing </body> tag as there's still remaining HTML to be rendered.

You're best approach will be to add a small snippet of Javascript of code before the closing </body> tag of your template:

<script>
// Lazy load all your CSS and fonts
for (const css of [
  '<?php echo $this->baseurl . '/templates/' . $this->template . '/css/template.css'; ?>',
  // You can define more CSS or font files here in the array
]) {
  const link = document.body.appendChild(document.createElement('link'));
  script.rel = 'stylesheet';
  script.href = css;
}

// Lazy load all your JS
for (const js of [
  '<?php echo $this->baseurl . '/templates/' . $this->template . '/css/template.js'; ?>',
  // You can define more Javascript files here in the array
]) {
  const script = document.body.appendChild(document.createElement('script'));
  script.async = false;
  script.src = js;
}
</script>

Note that I've written this in ES6. You can transpile back to ES5 if you wish to support IE11.

If I understand the usage of preload correctly, in 3.x you can add these links manually with addHeadlink():

// Preload resources
$mediaVersion = $this->mediaVersion ? '?' . $this->mediaVersion : '';
$this->addHeadLink($this->baseurl . '/templates/' . $this->template . '/css/template.css' . $mediaVersion, 'preload', 'rel', array('as' => 'style'));
$this->addHeadLink($this->baseurl . '/templates/' . $this->template . '/js/template.js' . $mediaVersion, 'preload', 'rel', array('as' => 'script'));

// Load resources
JHtml::_('script', 'template.js', array('version' => 'auto', 'relative' => true));
JHtml::_('stylesheet', 'template.css', array('version' => 'auto', 'relative' => true));

Note, document's $mediaVersion property works when added resources have auto value for version. If you're using a different method for generating version, change it on preload links accordingly.

It seems that Joomla 4.0 will have this possibility:

https://github.com/joomla/joomla-cms/pull/15880

  • This post is low-value in terms of what will stand the test of time on Joomla Stack Exchange. It is important that when you post "an answer" that it is not merely a "link-only answer". Links are fragile -- if they get moved or removed from the destination site, you answer will be rendered entirely useless. The truth is, your post is only mentioning that this issue is a possibility in Joomla 4.0 and is not actually a "solution". I will advise you to remove this post and instead write it as a comment under your question or add it to your question body. I have flagged as "not an answer". – mickmackusa Nov 17 at 21:58
  • That said, once this solution is a legitimate solution in J4.0, then you are welcome to edit this post into a complete and educational solution and then undelete it so that it is available for future researchers. – mickmackusa Nov 17 at 21:59

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.