XF 2.3 Boosting performance in XenForo 2.3

googlechrome.github.io_lighthouse_viewer_ (4).png
In today's 'Have you seen...?' entry for XenForo 2.3 we're going to look at how we've zeroed in on enhancing performance, ensuring your community has a swift and seamless experience. We're going to take a deep dive into the advancements we've made and how they stack up against various performance metrics.

But, before we get into the individual changes, let's take a quick look at the baseline - this is our current Performance score as calculated by Lighthouse for the XenForo Community forum list:

googlechrome.github.io_lighthouse_viewer_.png

Here's the performance scores for some other forum software:

1.png
2.png
3.png

It's crucial to note that while this score provides a performance benchmark, it isn't the only indicator of success. Indeed, results can fluctuate slightly with multiple test runs. A site can still enjoy popularity with a lower score, but a higher rating undeniably enhances both search engine rankings and overall user experience.

Stay tuned! We'll reveal XenForo 2.3's updated score shortly. But before that, let's dive into the changes that have brought us here, shall we?

If you would like to jump to a particular section, use the links below.
Alternatively, if you want to skip a whole lot of reading, check out the TL;DR below:

To view this content we will need your consent to set third party cookies.
For more detailed information, see our cookies page.

Oh and if you're concerned that all we've got to show you in XenForo 2.3 is performance improvements - fear not.

We will be showcasing a brand new feature next week!
 
Ya, agreed… but trying to do it for JavaScript (pre-compressed) is a little trickier… usually requires some web server config where it looks for a pre-compressed version). With SVG, it’s literally just compressing it and serving the compressed file (no web server trickery).

The reasoning of not wanting to save disk space or CPU cycles on each request would be along the same lines of not wanting to do any jpeg compression because the web server will perform compression on the fly. I mean ya… but why? 😀

If XenForo doesn’t end up doing it, it will hopefully be a simple enough addon. 🤷🏻‍♂️
 
Ya, agreed… but trying to do it for JavaScript (pre-compressed) is a little trickier… usually requires some web server config where it looks for a pre-compressed version). With SVG, it’s literally just compressing it and serving the compressed file (no web server trickery).
Anecdotally I have seen some web servers which wouldn't serve svgz files properly out of the box, but maybe the standard configurations are better these days 🤷‍♂️

The reasoning of not wanting to save disk space or CPU cycles on each request would be along the same lines of not wanting to do any jpeg compression because the web server will perform compression on the fly. I mean ya… but why? 😀
It's not that I disagree with the principle, I just personally think, in an ideal world, that resolving this is the job/domain of the web server (or CDN) rather than the application. Of course, we don't live in this fantasy world so... we'll see. If we don't do it, it should be trivial to implement via an add-on.
 
Anecdotally I have seen some web servers which wouldn't serve svgz files properly out of the box, but maybe the standard configurations are better these days 🤷‍♂️
Did they serve svg okay? I guess if they just didn't define that extension/mime-type, but strange that any web server would be setup for svg byt not svgz (even the mime-type is the same for both). Nginx for example doesn't even bother to give them their own line in the config, so someone would literally need to go out of their way to edit (and not delete) the line to remove svgz support but leave svg support:

Code:
image/svg+xml                                    svg svgz;

It's not that I disagree with the principle, I just personally think, in an ideal world, that resolving this is the job/domain of the web server (or CDN) rather than the application. Of course, we don't live in this fantasy world so... we'll see. If we don't do it, it should be trivial to implement via an add-on.
Yep, I certainly don't disagree, and for me it wouldn't affect much one way or the other because my images live on CDN. I really was just more curious than anything (although I'd probably still make an addon for it just for sake of efficiency). :)
 
Did they serve svg okay? I guess if they just didn't define that extension/mime-type, but strange that any web server would be setup for svg byt not svgz (even the mime-type is the same for both).
My memory is a bit fuzzy, but I think it was actually that they weren't setting the Content-Encoding header (or sometimes double-encoding the files, but I think that was down to non-standard configuration).

Yep, I certainly don't disagree, and for me it wouldn't affect much one way or the other because my images live on CDN. I really was just more curious than anything (although I'd probably still make an addon for it just for sake of efficiency). :)
I'm not trying to be stubborn and it's trivial enough :) I'll see if I can take a stab at it after some higher-priority items are sorted out.
 
With CloudFlare, the svg's will be cached and very likely in a compressed state or transcoded into whatever is the most efficient.

With css templates being served per-file, I'ld love is that integrated into friendly urls with a .css extension to allow cloudflare to cache the css out of the box without having to setup caching rules. That would be an end-user noticable improvement
 
With the minimum requirement of XF 2.3 being PHP 7.2.5 will you be completely removing vendor paragonie/sodium_compat. With Sodium being bundled with PHP 7.2.0+ this should save quite a few precompiled scripts from being included on what appears to be nearly every page request.

Currently running PHP 8.2+ and I'm still seeing PHP OPcache report these files being hit on nearly every page load...

community/src/vendor/paragonie/sodium_compat/lib/stream-xchacha20.php 5K
community/src/vendor/paragonie/sodium_compat/autoload.php 3K
community/src/vendor/paragonie/sodium_compat/lib/constants.php 7K
community/src/vendor/paragonie/sodium_compat/src/SodiumException.php 2K
community/src/vendor/paragonie/sodium_compat/src/Compat.php 273K
community/src/vendor/paragonie/sodium_compat/autoload-php7.php 2K
community/src/vendor/paragonie/sodium_compat/lib/php72compat.php 94K
community/src/vendor/paragonie/sodium_compat/lib/ristretto255.php 16K
community/src/vendor/paragonie/sodium_compat/lib/php72compat_const.php 5K
community/src/vendor/paragonie/sodium_compat/lib/sodium_compat.php 60K
community/src/vendor/paragonie/sodium_compat/lib/namespaced.php 3K
 

Native defer for JavaScript​

[...]

This allows the browser to start downloading the scripts slightly earlier, while deferring their execution until the rest of the DOM is loaded.
Just a note as this is not documented or obvious:

This change caused a backwards incompatible change to \XF\Template\Templater::getIncludedJs:
In XF 2.0-2.2 it returned an array with numeric keys and the JS URLs as values, in XF 2.3 it returns an array with the URLs as keys and defer as bool.
 
Have you resolved the slow queries in the gallery with this release, so we can show all gallery photos no matter when uploaded, so the page loads faster than one minute per page?

You've been promising this to us for 4 years now and every time I post my question, you deleted it.
 
We do not currently have an update on anything related to XFMG. This will be provided aa the Beta process progresses.
 
Have you resolved the slow queries in the gallery with this release, so we can show all gallery photos no matter when uploaded, so the page loads faster than one minute per page?

You've been promising this to us for 4 years now and every time I post my question, you deleted it.
That sounds like XFMG, this is XenForo (core).
 
Font Awesome

In Xenforo 2.1/2.2 it was possible to do smth. like
HTML:
<xf:button href="https://..." class="button--link button--icon button--icon--hide">Test</xf:button>

<a class="button--link button--icon button--icon--hide button" href="https://...">
    <span class="button-text">
        Test
    </span>
</a>
to get a "button link" with a FA icon.

This does not work in XF 2.3 - is this intended behaviour or a bug?

If it is a bug I'll report it, if it is intended behaviour I might havbe have to create new CSS classes to achive the required effect.
 
That functionality is still there, but the icon analyzer doesn't pick it up. Would be worth posting it as a bug, though the syntax we've expected there has always been:

HTML:
<xf:button href="https://..." class="button--link" icon="hide">Test</xf:button>

The icon attribute automatically sets the button--icon class and adds the button--icon--hide class.

Of course the fa attribute is even more flexible as it can use any icon (and any style):

HTML:
<xf:button href="https://..." class="button--link" fa="fad fa-eye-slash">Test</xf:button>
 
That functionality is still there, but the icon analyzer doesn't pick it up. Would be worth posting it as a bug
Thanks for the clarification, I've filed a burg report.

 
In XenForo 2.3, we've optimized this functionality by refining how CSS requests are made.
  • The core CSS, which is consistent across all pages, continues to be bundled into a single request.
  • CSS specific to individual templates or pages will now be requested separately, rather than bundled together.
Is this included in Beta 1 that customers can download?

This is being done on xenforo.com but does not happen wih my test installation and looking at the code there seems to be only one reference to css.php that creates a "single request" URL just like XF 2.2 did.
 
If we can’t detect HTTP/2 (due to a reverse proxy, for example) then it requires a config flag. I forget the name of it off-hand but I can double check when I’m back at my desk if you don’t get to it first.
 
PHP:
$config['enableCssSplitting'] = true;

That did the trick, now I need to find out why autodetect fails :)

Edit
Also works with autodetect now; HTTP/2 was not enabled in HAProxy backend so the backend connection was HTTP/1.
grmpf
 
Last edited:
Top Bottom