Web Hosting and SEO

Configuring Server Side Page Caching in Joomla

Server side page caching is an important part of reducing the render time for your web site and thus improving your user experience. The load time is also used by Google and other search engines to assist in ranking pages--faster page loads will result in better rankings. Joshua Bixby provides and excellent discussion of how load times are calculated by search engines in 13 Questions (and Answers) About Google, Site Speed and SEO. The article that follows describes how to use Joomla's built-in caching capabilities, how to use Akeeba Admin Tool’s .htaccess generator to improve performance, how to configure a popular caching extension to further improve web site performance, how to use various image optimization tools for lossless compression, and how you should set up JavaScript for asynchronous loading. The article discusses Google’s PageSpeed utility as a way to test the results of various configuration changes. The article is divided into the following sections:

Google PageSpeed Webmaster Tool

The article that follows is shows how to use Joomla settings and the JBetolo extension to improve page loading time and in particular, to improve the Google PageSpeed score for a page. PageSpeed is a utility for analyzing the way a page is optimized to reduce the time it takes to render the page in a browser. A good PageSpeed score is helpful in getting a good user experience in many cases. For a low volume web site where the server cache expires before every access, turning on the various settings for caching can actually slow down the render time as the server rebuilds the cache before serving the page. In this low volume case, getting a good PageSpeed score for your site will actually hurt your render times. You will have to experiment to determine what works best for rendering your web site.

The PageSpeed is located at https://developers.google.com/speed/pagespeed/insights/?hl=en&utm_source=wmx&utm_campaign=wmx_otherlinks.

To use PageSpeed, just enter the URL of the page that you want to analyze. All of the examples in this article are from the page https://www.mooresoftwareservices.com/loan-pricing/9-effective-yield-loan-fee-amortization on this site. The page contains basic HTML, tables, and calls to MathJax to render mathematical formulas, but it does not contain much in the way of images. Figure 1 shows the Google PageSpeed rating for this page with no compression or caching enabled.

Figure 1. The Google PageSpeed utility output for the basic site with neither caching nor compression enabled.
The Google PageSpeed utility output for the basic site with neither caching nor compression enabled

The Google PageSpeed algorithm rewards a number of things, that generally fall in three categories for items that can be improved via Joomla and JBetolo configuration:

  • Minify
  • Compress
  • Merge

These three categories will be described in the following sections.

Minify

Minifying a file is the process of removing unnecessary characters from the file, typically spaces, line end characters, comments and other characters that are not needed to for correct execution of the file. A minified file does not need to be “un-minified” by the client browser. Minifying generally does not break things on a Joomla web site, but it does take server processing.

Compression

Compression is the process of reducing the size of the file using a compression program. Unlike a minified file, a compressed file DOES need to be uncompressed prior to execution by the client browser. Compression generally does not break things on a Joomla web site, but it does take server processing.

Merging

Merging is the process of combining a number of CSS or JavaScript files into a single CSS file and a single JavaScript file. Because browsers generally only open two download channels to a host at a time, there is a lot of overhead in starting the download processing for a large number of CSS and JavaScript files. By merging files, you can speed up the download process by eliminating the overhead of starting all of the different streams. Merging files frequently DOES break things with other Joomla extensions. You will need to do a lot of testing before you turn merging on in production.

Native Joomla Caching and Compression

Joomla has a basic built-in compression and caching capability that is implemented by setting Joomla configuration variables in the configuration.php file. Joomla does not have a native merging capability. The Joomla native caching has one major drawback--all article retrievals from cache will not be reflected in the hit counts for the articles. In the Global Configuration panel shown in Figure 2, setting the file type and cache time will set the cache variables as shown Figure 3:

Figure 2. The Joomla Global Configuration system panel showing the settings for Joomla native caching.
The Joomla Global Configuration system panel showing the settings for Joomla native caching
Figure 3. The lines in the configuration.php file that the Joomla Global Configuration system panel changes.
public $caching = '0'; public $cache_handler = 'file'; public $cachetime = '10';

Similarly, the native setting for GZIP compression is on the system panel as shown in Figure 4.

Figure 4. The Joomla Global Configuration server panel showing the setting for turning on GZIP compression.
The Joomla Global Configuration server panel showing the setting for turning on GZIP compression

For my web page, the native Joomla cache and compression settings didn't really improve the PageSpeed score and that much and broke the Joomla internal hit counters for articles so that I didn't have accurate information on which articles were getting traffic. At this point, I started looking for extensions that would handle the caching and which would maintain accurate hit counts for all of my articles.

Using Akeeba Admin Tools to Generate .htaccess

Akeeba Admin Tools have the capability to generate a .htaccess file that will do a great deal to secure your Joomla web site, but which will also set up the compression and most of what you need to get a good score on Google PageSpeed. In the section Custom .htaccess rules shown in Figure 5, add the local caching rules listed in Figure 15.

Figure 5. Akeeba Admin Tools custom .htaccess rules for local browser caching.
Akeeba Admin Tools custom .htaccess rules for local browser caching

Using the JCH Optimize Extension to Compress, Minify, and Merge

To improve PageSpeed scores and speed up a site, there are a number of Joomla extensions that offer improved caching, minification, compression, in addition to consolidation of JavaScript and CSS files, plus lazy loading of images. After some trial and error, I ended up using the paid version of JCH Optimize for caching, minification, consolidation and lazy loading. With about four hours of testing, I was able to get all pages on my site to render properly; the problematic pages and the solutions are discussed in the sections that follow:

Basic JCH Optimzie Configuration

JCH Optimize has a great set of standard settings shown in Figure 6 that progressively turn on additional features that make it easy to test which settings break which pages. Most of the pages on this site worked with “Average” but with some additional testing, I was able to get more aggressive in the settings. The only thing basic setting that I have not been able to enable is the “Defer JavaScript” option shown in Figure 7. The next section describes the changes necessary to get the Google Trends displays working properly.

Figure 6. The JCH Optimize main panel has pre-configured settings that you can use to determine which settings cause problems on particular pages.
The JCH Optimize main panel has pre-configured settings that you can use to determine which settings cause problems on particular pages.
Figure 7. For this site, only the defer JavaScript option creates problems.
For this site, only the defer JavaScript option creates problems.

A number of the articles on this site use Google Trends embedded JavaScript calls within an article; Traffic2cash.xyz Google Analytics Referral Spam is an example of an article that shows Google search trends. To get these to work, I had to disable the JavaScript consolidation option for scripts that occur between the <body> and </body> tags as shown in Figure 8. This option is only turned on in the higher levels of optimization in JCH Optimize.

The next section discusses the changes necessary to get MathJax working properly.

Figure 8. On this site, the search body option causes problems with <script> tags used to display Google Trends graphics.
On this site, the search body option causes problems with script tags used to display Google Trends graphics.

Getting MathJax Formulas to Render Properly

To use the advanced settings in JCH Optimize, you will almost certainly need to exclude some extensions or scripts from the consolidation and other advanced features; this is done in the “Exclude Options” tab in JCH Optimize. Many of the pages on this site use MathJax to render mathematical formulas; Effective Interest (Yield) Amortization of Loan Points to Income is an example of an article that uses MathJax to render formulas. MathJax requires calling a JavaScript program in the header to a site. I use the JaTex plugin to do this. To get these formulas to render properly, I had to exclude this extension from the JavaScript consolidation as shown in Figure 10.

The next section discusses how to use the advanced settings to get Google Analytics to work.

Figure 9. The Exclude Settings tab in JCH Optimize is perhaps the most important for getting unusual pages to work properly
The Exclude Settings tab in JCH Optimize is perhaps the most important for getting unusual pages to work properly
Figure 10. In JCH Optimize, the Mathjax extension must be excluded in order to math formulas to render properly.
In JCH Optimize, the Mathjax extension must be excluded in order to math formulas to render properly.

Getting Google Analytics to Work Properly

Many Joomla sites use Google Analytics for search engine optimization (SEO) analysis, and use the sh404SEF to manage the insertion of the code to call Google Analytics for visit logging. To get this to work, you will need to exclude this script as shown in Figure 11. To test this, you will need to go to the “Real Time” section in Google Analytics without any filters for your home location and then open a browser that does not disable tracking to force activity in Google Analytics. If everything is working properly, you will see your browsing activity in the Real-time section of Google Analytics.

The next section shows how to enable lazy loading for images.

Figure 11. When using JCH Optimize and sh404SEF together, you will need to exclude this sh404SEF script in order to get Google Analytics to work properly
When using JCH Optimize and sh404SEF together, you will need to exclude this sh404SEF script in order to get Google Analytics to work properly

Getting Template Images to Work with Lazy Loading

If you have articles with a large number of screen captures or other images (like this article), you may want to enable lazy loading of images to reduce server load and improve page load times. With lazy loading enabled, an image does not load until the reader scrolls down to that portion of the article. With lazy loading enabled, you may need to exclude some images that are displayed as part of the template, as shown in Figure 13.

The next section talks about optimizing CSS delivery to improve render time.

Figure 12. With lazy loading enabled under Pro Options, logo and other template-based image files may need to be excluded from lazy loading
With lazy loading enabled under Pro Options, logo and other template-based image files may need to be excluded from lazy loading

CSS Delivery

In Google PageSpeed, one of the metrics discusses reducing the amount of data that must be downloaded before the first screen can be rendered. Under the Pro Options in JCH Optimize, you can attempt to do this using the “Optimize CSS” delivery option. This option can take some significant trial-and-error testing and is probably the option most likely to break after system maintenance.

Figure 13. Under Pro Options, the Optimize CSS delivery option will probably require the most testing
Under Pro Options, the Optimize CSS delivery option will probably require the most testing

Using the JBetolo Extension to Compress, Minify, and Merge

This article was originally written to describe setting up server side caching with jBetolo, but I had repeated problems getting it to work propery with MathJax, the Joomla print/email icons (an icon font) and other things so I switched to the paid JCH Optimize plugin and have had a much easier time getting that plugin to work.

Image Compression with optipng

PageSpeed will point out any PNG images that need to be compressed. For PNG images, the optipng command line utility available from http://optipng.sourceforge.net/ will compress images and make PageSpeed happy. On Ubuntu, you can install this with the command sudo apt-get install optipng, while on windows you will have to download and install the binary from the SourceForge web site. Figure 14 shows how to call optipng from the command line to compress all of the files in a directory.

Figure 14. The optipng command and sample output.
optipng *.png ** Processing: joomla_admin_config_server_compression.png 979x881 pixels, 4x8 bits/pixel, RGB+alpha Input IDAT size = 157917 bytes Input file size = 158027 bytes Trying: zc = 9 zm = 8 zs = 0 f = 0 IDAT size = 157917 joomla_admin_config_server_compression.png is already optimized.

Image Compression with jpegtran

PageSpeed will point out any JPEG images that can be compressed. For JPEG images, the jpegtran command line utility available from http://jpegclub.org/ will losslessly optimize the internal structures in JPEG images and reduce the size by 10-20% in many cases without loss of image quality. The command is not quite as simple as the optipng tool, as you will either need to write a script or run the command several times:

jpegtran -copy none -progressive -optimize input.jpg > output.jpg

Client Side Caching

The final step in setting up caching is to configure the client browser expiration settings for your web site. Google PageSpeed recommends setting the client side cache expiration to a minimum of one week (604,800 seconds), which works well for most content. The .htaccess generator in Akeeba Admin tools will do this for you but if you are not using Akeeba Admin Tools, you will want a section in your .htaccess that looks something like the example shown in Figure 15.

Figure 15. Example client side cache expiration definitions in the .htaccess file.
# # Expiration # # # Expiration # ExpiresActive On ExpiresDefault "now plus 1 hour" # CSS and JS expiration: 1 week after request ExpiresByType text/css "now plus 1 week" ExpiresByType application/JavaScript "now plus 1 week" ExpiresByType application/x-JavaScript "now plus 1 week" # Fonts ExpiresbyType application/x-font-ttf "now plus 1 month" ExpiresbyType application/octet-stream "now plus 1 month" ExpiresbyType font/truetype "now plus 1 month" ExpiresbyType font/ttf "now plus 1 month" ExpiresbyType application/x-font-woff "now plus 1 month" ExpiresbyType application/font-wof "now plus 1 month" ExpiresbyType application/x-woff "now plus 1 month" ExpiresbyType application/vnd.ms-fontobject "now plus 1 month" # Image files expiration: 1 month after request ExpiresByType image/bmp "now plus 1 month" ExpiresByType image/gif "now plus 1 month" ExpiresByType image/jpeg "now plus 1 month" ExpiresByType image/jp2 "now plus 1 month" ExpiresByType image/pipeg "now plus 1 month" ExpiresByType image/png "now plus 1 month" ExpiresByType image/svg+xml "now plus 1 month" ExpiresByType image/tiff "now plus 1 month" ExpiresByType image/vnd.microsoft.icon "now plus 1 month" ExpiresByType image/x-icon "now plus 1 month" ExpiresByType image/ico "now plus 1 month" ExpiresByType image/icon "now plus 1 month" ExpiresByType text/ico "now plus 1 month" ExpiresByType application/ico "now plus 1 month" ExpiresByType image/vnd.wap.wbmp "now plus 1 month" ExpiresByType application/vnd.wap.wbxml "now plus 1 month" ExpiresByType application/smil "now plus 1 month" # Audio files expiration: 1 month after request ExpiresByType audio/basic "now plus 1 month" ExpiresByType audio/mid "now plus 1 month" ExpiresByType audio/midi "now plus 1 month" ExpiresByType audio/mpeg "now plus 1 month" ExpiresByType audio/x-aiff "now plus 1 month" ExpiresByType audio/x-mpegurl "now plus 1 month" ExpiresByType audio/x-pn-realaudio "now plus 1 month" ExpiresByType audio/x-wav "now plus 1 month" # Movie files expiration: 1 month after request ExpiresByType application/x-shockwave-flash "now plus 1 month" ExpiresByType x-world/x-vrml "now plus 1 month" ExpiresByType video/x-msvideo "now plus 1 month" ExpiresByType video/mpeg "now plus 1 month" ExpiresByType video/mp4 "now plus 1 month" ExpiresByType video/quicktime "now plus 1 month" ExpiresByType video/x-la-asf "now plus 1 month" ExpiresByType video/x-ms-asf "now plus 1 month"

The font moonico.woff requires the application/x-font-woff two entries in the expiration list, and may require others. This font is used for the print, email, edit and search icons and is the most difficult thing to get working reliably with Jbetolo. Without these entries, you will have a page that looks fine until it expires.

Using Asynchronous Loading for JavaScript

The page that I used for testing in this example calls MathJax to render some mathematical formulas. MathJax is implemented in JavaScript and is called via

<script type="text/JavaScript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"> </script>

If you are not using a plugin to add the MathJax code, you can converting this synchronous script loading to asynchronous loading by adding async to the call got rid of the red “You Should Fix” section of recommendations in the PageSpeed list for this page and improved the PageSpeed score by one point. The asynchronous syntax is shown below:

<script async type="text/JavaScript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"> </script>

Testing

It is important to test using all major browsers, as optimizations that work in Firefox and Safari may not work in Chrome and Internet Explorer, both of which are more common. If figuring out what is going on and what is blocking rendering, the Firefox developer tools can be quite useful. Figure 11 shows the a native compression only retrieval of the page while Figure 11 shows a retrieval with merging turned on for both CSS and JavaScript. Note that the JBetolo time is about 10% shorter than the native time (1.88 vs. 2.08), and that the time to render the first display is shorter still, though the latter isn't easy to tell from the displays. Make sure to do several retrievals, as they will vary dramatically from retrieval to retrieval depending upon server and network load, the 1.88 and 2.08 are not statistically valid numbers in any way. The most obvious difference is that the number of bytes required has been cut by more than 50%, from 744K to 354K. The results reported by Google Analytics are probably the best measure of how well your optimizations are working.

Figure 16. Firefox developer mode showing timing of retrieval for native compression only.
Firefox developer mode showing timing of retrieval for native compression only
Figure 18. Firefox developer mode showing timing of retrieval for JBetolo with merging, minification and compression.
Firefox developer mode showing timing of retrieval for JBetolo with merging, minification and compression

Google Analytics Timing Results

For a 30 day period where the no caching was enabled but compression was enabled (PageSpeed score of 67 for example page), Google Analytics reported an average load time of 5.12 seconds. Average load times with merging, minification and compression turned on in JCH Optimize will be added at a future date, but appear to be under 2 seconds.