An elegant way to serve gzipped HTML?

I ran an audit in the Developer Console of Google Chrome and it suggested me, to serve compressed HTML. In PHP, this is usually a one-liner, you need to put into your scripts before any output:

<?php
ob_start('ob_gzhandler');
?>

If I put it into my header-snippet, this does not work. If I put it into my config file, it does. But putting it there would mean, that any output would be gzipped, which makes no sense, when serving images or downloads through PHP. This currently not an issue for me, but it doesn’t feel right, to put this line info config.php. I would like to have a solution that works in any of my future kirby-projects. Any suggestions how to make this work in a more elegant way?

My understanding is that gzipping belongs to your web server config. Nginx had gzip on by default, but didn’t include css files or some such if I remember correctly, so I had to tweak the gzip_types setting a bit.

I use the following in my nginx.conf:

gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

Instructions for other servers should be easy to find I hope. :smile:

That is my understanding as well, if gzipping is enabled on the server, you can do your settings in httpd.config or your .htaccess on an Apache server.

Yes, this is possible by adding the following line to your .htaccess:

 AddOutputFilterByType DEFLATE text/html

Details about that can be found in the Apache documentation.

Apparently, Apache doesn’t cache this gzipped version of a file. So everytime a file is requested, the server has to re-compress it. I made a test, using a 1.7 mb JavaScript file (it came with Bootstrap). Loading it in Firefox took 200 ms on my local machine, compared to about 60 ms when serving the uncompressed version.

So in practive, I think this is wasted CPU time (especially on cheap hosting). If you use a build-tool like gulp, than it’s pretty easy to store a pre-gzipped version alongside the minified version of a file on the server and use .htaccess and mod_rewrite to serve that file, so gzip does not have to work everytime a file is requested. For Example:

assets/css/
  screen.min.css
  screen.min.css.gz

In your .htaccess file you could redirect like this:

# Serve gzip-compressed JS/CSS files if they exist and the client accepts gzip

RewriteEngine On
RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{DOCUMENT_ROOT}/$1\.$2\.gz -s
RewriteRule ^(.*)\.(?:\d+\.)?(css|js)$ $1\.$2\.gz [QSA]

<FilesMatch \.css\.gz$>
  ForceType text/css
  Header append Vary Accept-Encoding
</FilesMatch>
<FilesMatch \.js\.gz$>
  ForceType application/javascript
  Header append Vary Accept-Encoding
</FilesMatch>

AddEncoding gzip .gz

# Fallback for files that don’t have a gzipped version
RewriteRule ^(.*)\.\d+\.(css|js) $1\.$2 [QSA]

Note that this example also includes a so-called cachebuster redirect, e.g.:

assets/css/screen.min.8012345.js

This is used to prevent the browser from using an old version of a file, stored in the cache.


Anyway, thank you for the hint with the .htaccess file for gzipping. When a user accesses a page, PHP is involved anyway, so the little performance-loss of gzippin’-on-the-fly is something, I can live with. :slight_smile:

1 Like