One crucial method to speed up your page load time is to force your web server to send out the Cache-Control HTTP header in its response headers.

This header is defined by the HTTP specification


Introduction

By utilizing the Cache-Control HTTP header you can avoid unnecessary network requests and they will be supported by default from all browsers your visitors are using to visit your page.

I will focus in this post on the Apache HTTP Server and how you can here implement in just a few seconds the Cache-Control HTTP header.

In the figure below you will see for example the response headers from my own blog, captured by using Fiddler, a web debugging proxy tool. The max-age value in the Cache-Control header from the web servers response headers is shown in seconds here and are finally 7 days.

These HTTP headers are an instruction to the client about the document’s validity and persistence. If cached, the document may be fetched from the cache rather than from the source until this time has passed. After that, the cache copy is considered “expired” and invalid, and a new copy must be obtained from the source.

Source: https://httpd.apache.org/docs/2.4/mod/mod_expires.html



Set up expires HTTP Headers on Apache

For the Apache HTTP server you can set these headers either directly in the main configuration file (usually called httpd.conf or on Ubuntu /etc/apache2/apache2.conf), or by using the virtual host configuration files within the /etc/apache2/sites-available directory when running multiple web sites on the web server, or you can also set them by using a .htaccess file.

In my case I will using the virtual host configuration files within the /etc/apache2/sites-available directory.

Below you will see the expires directives I will use for my blog in the corresponding virtual host config file.

ExpiresActive on
ExpiresDefault "access plus 1 month"
ExpiresByType text/html "access plus 1 weeks"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/webp "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 month"


The expiration date can set to be relative to either the time the source file was last modified, or to the time of the client access. Above I will use here the time of the client access by using:

ExpiresDefault "access plus 1 month"

# and by type
ExpiresByType text/html "access plus 1 weeks"

The following keywords for the expiration date event can be used:

  • access
  • now (equivalent to ‘access’)
  • modification


The plus keyword is optional and its value should be an integer value, the following keywords are available:

  • years
  • months
  • weeks
  • days
  • hours
  • minutes
  • seconds


For example, any of the following directives can be used to make documents expire 1 month after being accessed, by default:

ExpiresDefault "access plus 1 month" 
ExpiresDefault "access plus 4 weeks" 
ExpiresDefault "access plus 30 days"

The expiry time can be fine-tuned by adding several num type clauses:

ExpiresByType text/html "access plus 1 month 15 days 2 hours" 
ExpiresByType image/gif "modification plus 5 hours 3 minutes"


Google recommends a minimum cache time of one week and preferably up to one year for static assets, or assets that change infrequently. 

Source: https://developers.google.com/speed/docs/insights/LeverageBrowserCaching


More about you will find in the following article https://httpd.apache.org/docs/2.4/mod/mod_expires.html.





Troubleshooting

On a new Ubuntu 22.04.3 LTS server I was running into to following error when restarting the Apache web server after adding the expires headers as shown above.

Invalid command ‘ExpiresActive’, perhaps misspelled or defined by a module not included in the server configuration


So looks like the expires_module is not loaded already by Apache. To enable and load it you can run the following command.

$ sudo a2enmod expires




More about to speed up your page load time by using for example the Redis object cache you can read my following post.





Links

Apache Module mod_expires
https://httpd.apache.org/docs/2.4/mod/mod_expires.html

Leverage Browser Caching
https://developers.google.com/speed/docs/insights/LeverageBrowserCaching

Performance Audits
https://developer.chrome.com/docs/lighthouse/performance/

Prevent unnecessary network requests with the HTTP Cache
https://web.dev/articles/http-cache#cache-control