Skip to main content

Setting Up a Cloudfront CDN for Rails

Setting Up a Cloudfront CDN for Rails?

Implementing a CDN to serve compiled assets in Rails is one of the most significant performance enhancements I’ve seen. Having done so for 2 fairly large applications, it’s hard for me to imagine serving assets locally anymore.
The Asset Pipeline

The addition of the Rails asset pipeline has reduced both the number of assets served and the size of these files. Users on slow connections have been the biggest beneficiary of these changes.
The Problem

Even with the asset pipeline, content is transmitted to the end user over their, sometimes slow, connection. Distance plays a role in the speed at which data can be delivered. Because of this, users further away from your servers get a sluggish experience. This decreases both the users’ patience and your ability to effectively engage them.
The Solution

CDNs are networks of servers that host your content so that when you make a request, the request is served from a server closest to you. This can often reduce transmission time by several seconds (…think users in Asia requesting content that’s served from Virginia – this is the case if you deploy to Heroku).

The use of a CDN also reduces the number of requests to your application servers. Most Ruby applications use Nginx or Apache in front of the Ruby processes. These HTTP servers are really good at serving static content, but no one will deny – the fewer requests, the better.
Option 1: Push your assets to the CDN during deployment

Depending on your method of deployment, pushing assets to a CDN isn’t always trivial. The asset_sync gem has made this relatively straight forward if you choose to host your assets from Amazon S3. Out of the 2 options, this is the most efficient because all requests for assets will be diverted away from your application, leaving its precious processing power to serve more important application requests.
Option 2: Assets are pulled to the CDN on first request

This option won’t change deployment and is simple to setup. The only downside is that upon first request to an asset, the CDN will pull it from your web server and cache it (it’s hardly a downside if you’re currently serving all your assets from your web server). All subsequent requests to that asset will be served straight from the CDN. The simplicity of this option generally makes it my preferred option.

So let’s get to it…
Amazon Cloudfront

Log in to your Amazon EC2 account and click “Cloudfront”:

"Click Cloudfront in the AWS web console"

Click “Create Distribution”:

"Create a Cloudfront distribution endpoint"

Enter the domain where your assets currently live (ignore Origin ID – it’ll be filled in for you):

"Settings for a typical CDN"

Make note of the Cloudfront distribution URL

"Cloudfront distribution URL"
Rails

Rails provides and easy way to change the host URL of the assets (images, stylesheets, javascripts, fonts…). Enter the Cloudfront distribution URL from above as the Rails asset_host.

# config/environments/production.rb
config.action_controller.asset_host = "d24xjtg100euk4.cloudfront.net"

At this point, the domain of all Rails asset helpers image_tag, stylesheet_link_tag, and javascript_include_tag will be prefaced with the asset host URL that you configured above.

For example:

image_tag("shark_teeth.png")
# http://d24xjtg100euk4.cloudfront.net/assets/images/shark_teeth.png

Note: if you only change config/environments/production.rb, you won’t see any changes in your development environment.

And that’s it!
In Summary

This is the ultimate low-hanging fruit optimization. If you haven’t served your assets from a CDN before, I’d suggest giving it a try. The cost of Cloudfront is minimal, and in my mind, worth 10x that.

I’ve recently been trying out a service called Fastly, which is an alternative to Cloudfront. It’s slightly more expensive, but seems to have better and more consistent performance.


Comments

Popular posts from this blog

Gem::LoadError (Specified 'mysql2' for database adapter, but the gem is not loaded. Add `gem 'mysql2'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord).?

Gem::LoadError (Specified 'mysql2' for database adapter, but the gem is not loaded. Add `gem 'mysql2'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord).) In rails?


1)change the gemfile in mysql version
 gem 'mysql2'

2)Change to mysql2 version
 gem 'mysql2','0.3.20'

Active Scaffold : Add radio buttons to your form ruby on rails ?

Active Scaffold : Add radio buttons to your form ruby on rails ?

The way to add radio buttons to your active scaffold create/update from is as shown below

#Controller

class UsersController < ApplicationController
active_scaffold :user do |config|
config.label = “Users”
config.columns = [:name, :gender]
config.columns[:gender].form_ui = :radio
config.columns[:gender].options[:options] = [['Male', '1'], ['Female','2']]
end
end

Get the Current url in ruby on rails

request.refererrequest.fullpathrequest.fullpath.split("?")[0]request.referer or request.env['HTTP_REFERER'] your controller to get the referer url. 

--------------------
request.original_url
request.url
request.host_with_port
<link rel="canonical" href="<%= request.url %>" />
<%=request.path%>
How can I get the current absolute URL in my Ruby on Rails view?
The request.request_uri only returns the relative URL.
request.env['REQUEST_URI']

 For Rails 3.2 or Rails 4 you should use request.original_url to get the current URL. More detail.

For Rails 3: You want "#{request.protocol}#{request.host_with_port}#{request.fullpath}", since request.url is now deprecated.

For Rails 2: You want request.url instead of request.request_uri. This combines the protocol (usually http://) with the host, and request_uri to give you the full address