In the previous issue, I explained how the loading of a page can be sped up by offering the elements in a page in parallel.
This issue will go into the optimization of Apache and the way it offers data to clients. Since these are optimizations for Apache, not only WordPress will benefit, but almost any other website will as well. Because this was part of my challenge to speeds up my website, I named this post “Optimizing WordPress (part 2)”.
mod_expires
Browsers have the ability to temporarily save data to the hard drive: the Cache. By caching, files only need to be downloaded once. Each following time a file us needed, these can be loaded from the local cache, instead of being downloaded. To aid browsers with caching, you can load the mod_expires Apache module.
ExpiresActive On
Once enabled, the caching can be tuned with two directives:
ExpiresDefault "access plus 2 months 1 day 1 hour" # most files don't change often ExpiresByType text/html "access plus 1 week" # html will change somewhat more often ExpiresByType text/cssĀ "access plus 1 week" # css probably will too
- ExpiresDefault
The default time items may reside in cache. - ExpiresByType
Allows you to tune the caching by mime-type. When ExpiresDefault is set, ExpiresByType can be used to define exceptions. If ExpiresDefault is not set, caching will only be used for the mime-types you configure with ExpiresByType.
The mime-types that Apache understands are usually loaded from a mime-types ‘database’ (a plain-text file). Apache can be told from which file to load the mime-types by using the TypesConfig directive. For Red Hat, the default location for the mime-types database is /etc/mime.types, in FreeBSD the default location is /usr/local/etc/apache22/mime.types.
Setting the expire time can be done in years, months, weeks, days, hours and seconds. As you can see in the above example for ExpiresDefault, these can be combined.
The starting time from when the expire time will be calculated can be set in three ways:
- access
Start from the time the file was requested. - now
Same as access. - modification
Start from the moment the file was modified (or created, which is also a modification) on the server’s hard drive.
Using modification is only of use when the files are not dynamically created, but loaded directly from the servers hard drive. Dynamic files have no modification time, so a modification header will not be sent along with them.
mod_deflate
In the good old Apache 1.3 era, mod_deflate was better known as mod_gzip. Mod_deflate is a real time compression method which proves most useful when handling plain text files. By compressing the outgoing data, less data needs to be transmitted, which in turn leads to pages that load faster. It is good practice to not let mod_deflate compress files that are already compressed, like zip files or images. The extra compression is minimal and it basicly wastes CPU cycles.
Mod_deflate can be enabled by placing an outputfilter:
SetOutputFilter DEFLATE
The compression level can be set using DeflateCompressionLevel:
DeflateCompressionLevel [1-9]
The compression is minimal with 1, and maximum with 9.
By now, the following setting will probably not be needed anymore, but it shows how exceptions can be made for browsers:
# only partial gzip support BrowserMatch ^Mozilla/4 gzip-only-text/html # or none at all BrowserMatch ^Mozilla/4\.0[678] no-gzip # MSIE does support it and this rule exempts it from previous rule BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
Because we don’t want to compress images, zips, pdf’s and other compressed files any further, we add the follwing rule:
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|pdf|zip|rar)$ no-gzip dont-vary # Help proxies deliver the right content to their clients Header append Vary User-Agent env=!dont-vary
The Vary header is added to help proxy servers serve their clients with content-encodings the clients actually understand.
The big picture
All settings put together gives us the follwing piece of configuration:
# mod_expires start ExpiresActive On ExpiresDefault "access plus 2 months 1 day 1 hour" ExpiresByType text/html "access plus 1 week" ExpiresByType text/cssĀ "access plus 1 week" # mod_expires end # mod_deflate start SetOutputFilter DEFLATE DeflateCompressionLevel 9 # only partial gzip support BrowserMatch ^Mozilla/4 gzip-only-text/html # or none at all BrowserMatch ^Mozilla/4\.0[678] no-gzip # MSIE does support it and this rule exempts it from previous rule BrowserMatch \bMSIE !no-gzip !gzip-only-text/html # Don't touch already compressed files SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|pdf|zip|rar)$ no-gzip dont-vary # help proxies Header append Vary User-Agent env=!dont-vary # mod_deflate end
These settings can be appended to Apache’s main configuration.
Does it work?
Of course we want to know if all these settings actually do something. Apache can be told to log the level of compression:
DeflateFilterNote Input instream
DeflateFilterNote Output outstream
DeflateFilterNote Ratio ratio
SetEnvIf Request_URI \.gif image-request
SetEnvIf Request_URI \.jpg image-request
SetEnvIf Request_URI \.jpeg image-request
SetEnvIf Request_URI \.png image-request
SetEnvIf Request_URI \.zip image-request
SetEnvIf Request_URI \.rar image-request
SetEnvIf Request_URI \.pdf image-request
LogFormat '%V "%r" %{outstream}n/%{instream}n (%{ratio}n%%)' deflate
CustomLog /var/log/httpd/deflate.log deflate env=!image-request
The DeflateFilterNote settings tell Apache to append compression ratios to the logs. The SetEnvIf settings tell Apache not to log this for certain file extensions (we don’t compress these anyway). The results can be seen in the newly made logfile /var/log/httpd/deflate.log.
Pingback: Wordpress optimaliseren (deel 2) | Eelco