In a recent client project, in order to speed up the loading of assets and to improve the overall page speed score, I decided to store the assets outwith of the app and to be able to use the dynamic asset hosts functionality within rails.
This works really well out of the box apart from one caveat: the app uses Dragonfly to serve dynamic images which gets resized based on certain conditions.
I originally used asset_sync to store the precompiled assets into Amazon S3 but of course this fails miserably as S3 cannot find images with urls beginning with ‘/system/’ etc as that is supposed to be handled by the Dragonfly engine whereas asset_sync is looking for a folder or directory path inside S3 !!
Add to that the complexity of adding in a cloudfront CDN
The solution I came up in the end was not to use asset_sync but to precompile all the assets before deployment. Then I added a CNAME entry such as ‘assets.mysite.com’ to point to the actual domain ‘mysite.com’ This is what you would do anyway if you are using asset hosts. Make sure you wait and test the CNAME to make sure it points to the domain ‘mysite.com’ before proceeding further.
Then within the CDN, set up an origin for ‘assets.mysite.com’ and wait for it to finish setup and turn green. if you start testing before it turns green you will get some weird 503 unavailable errors or your assets will 404 with ‘Image returned with type of text/html’ etc
Within the config/production.rb add the following line:
config.action_controller.asset_host = "//test.cloudfront.net"
This will make sure that all the assets requests pass through to the CDN rather than the app itself. It also solves the problem of using a dynamic image engine such as Dragonfly while keeping your compiled assets intact on heroku.
Another issue to note is that on Heroku cedar stack there is no reverse proxy cache which means your html will not be minified. The following links from heroku mentioned this: Link 1 and Link 2. This can be fixed by using the heroku defalter gem which will automatically gzip both images and html responses.
In initial tests, the page speed for various pages drop from an intial 4-5ms to under 1ms when the CDN has cached all the assets properly.
If you still wish to use asset_sync to serve assets from S3 with Dragonfly, there are two possible options:
1. Generate a static image for each version required e.g. thumbnail version; actual version
2. Specify the host within the dragonfly initializer. In my case the dragonfly is within a gem which preloads it so i did not even attempt to spend hours overwriting the initializer.