Welcome daisy!

Setup done earlier for Apache2 + Rails wasn’t yet very optimal. This fact was neatly indicated by google pagepeed index tools. Luckily few fixes are rather easy to apply.

Assets not compressed
Ups, this is triviality, I had forgotten to copy relevant caching logic config when setting up new virtual host config.

# enable compression for all relevant assets

# normal web pages
AddOutputFilterByType DEFLATE text/html
# material icons and such
AddOutputFilterByType DEFLATE image/svg+xml
# XHR calls
AddOutputFilterByType DEFLATE application/json

BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
# Don’t compress images
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary


Notice that compression is not applied to all possible types. Reason for this lies ahead in the road, namely in the logic of dealing pre-created ”.gz” files by rails. In other words this is a bit hacky way of solving conflict arising with ”js.gz” and ”css.gz” matching.

Thumbnails not cached
Hmm… need to setup expiration when serving assets via ”send_file”.

class ThumbController
def show

response.headers[”Expires”] = CGI.rfc1123_date(Time.now + 365.days)
send_file …

Assets not cached properly
Trickier, apache2 + passenger + rails are not playing neatly together. Luckily this is not new problem and solution was readily available via apache conf for Rails asset pipeline.

First of all was necessary to enable ”headers” module for apache2, since seemingly it’s not enabled by default.

# Rails finger-printed assets, make them cached forever.
# Try only match if the asset actually has a fingerprint in it.

Header unset ETag
FileETag None
# RFC says only cache for 1 year
ExpiresActive On
ExpiresDefault ”access plus 1 year”


Pregenerated .gz files are not utilized for assets
Would be practical that web server would be able to directly server .gz -files generated by rails assets pipeline.

# Let apache serve the pre-compiled .gz version of static assets,
# if available, and the user-agent can handle it. Set all headers
# correctly when doing so.
# SOMEWHAT EXPERIMENTAL. If you think it’s causing problems,
# just remove the following three LocationMatch.

RewriteEngine on

# Make sure the browser supports gzip encoding before we send it,
# and that we have a precompiled .gz version.
RewriteCond %{HTTP:Accept-Encoding} \b(x-)?gzip\b
RewriteCond %{REQUEST_FILENAME}.gz -s
RewriteRule ^(.+)$ $1.gz

# Make sure Content-Type is set for ’real’ type, not gzip,
# and Content-Encoding is there to tell browser it needs to
# unzip to get real type.
# Make sure Vary header is set; while apache docs suggest it
# ought to be set automatically by our RewriteCond that uses an HTTP
# header, does not seem to be reliably working.

ForceType text/css
Header set Content-Encoding gzip
Header add Vary Accept-Encoding

ForceType application/javascript
Header set Content-Encoding gzip
Header add Vary Accept-Encoding


As you can see, logic is not dealing all possible cases properly (especially it’s not dealing bootstrap glyphfonts case). However, point here was to make some incremental improvement, and that goal should be now reached. Work what server needs to do to serve common resource cases should be now decreased. That said, I feel that this solution is still imperfect and requires further iteration. Additionally this struggle to get such basic logic to work causes consideration if host web server could be switched into nginx instead.

/ Development, Web