blog

Photo of hummingbird Photo by James Wainscoat on Unsplash

Faster web page requests in Rails development

by

Nobody likes waiting for a web page to load.  Pity, then, the Ruby on Rails developer, proud of the the development platform’s famous efficiency of code, combating the slanderous claims of a slow production environment, and then condemned to watch the browser bar spinning and spinning for the 500th time during today’s coding session.  Because Rails requests in the default development environment are s l o w.

Why?  By default, every web page request is verifying and recompiling every referenced asset — every Coffeescript, Sass, and Less file.  Ajax requests with responses that don’t include the application layout (and its application.js and application.css manifest file burdens), are delightfully zippy, but loading a simple home page?  Over and over throughout the course of the day?  Goodbye delight and efficiency.

Debug off

Until you make one simple change in development.rb:

# Expands the lines which load the assets
config.assets.debug = <strong>false</strong>

In my tests, disabling asset debug mode increased page response times by an order of magnitude!  Rails will still recompile all your assets — so any changes to the styles or front end code will be reflected in the page after a reload — though it won’t perform certain validation checks or split the requested Javascript and stylesheets into multiple files.

In trade for the speedup, disabling asset debugging will replace detailed asset syntax error exception pages like:

Sass::SyntaxError in Home#index
Showing app/views/layouts/application.html.erb where line #9 raised:

Invalid CSS after "}": expected selector or at-rule, was "}"
  (in app/assets/stylesheets/application.css.scss)

Extracted source (around line #9): etc.

with a much terser error or a runtime Javascript exception.

And instead of each individual asset files downloaded to the browser, like:

Software screen capture

you’ll only see your manifest files:

Software screen capture

Those are minor downsides for having far faster refresh cycles.  If you want to be able to re-enable asset debugging for individual requests, you can use the debug option of stylesheet_link_tag and javascript_include_tag.  For example:

<%= javascript_include_tag "application", debug:
    MyApp::Application.config.assets.debug ||
    Rails.env.development? && params[:jsdebug] %>

will debug the application.js manifest when either is true:

  1. asset debugging is configured
  2. ?jsdebug=true is appended to a URL in the development environment

Use a similar construct on <%= stylesheet_link_tag "application" %> with a parameter like cssdebug.  Then, rather than slowing down every request for debug info, you can quickly enable it from the browser only when necessary.

Asset logging off

When assets are requested by the browser, those requests are logged in voluminous detail in the output of rails server. You’ve probably noticed pages of messages like this one scrolling up in your terminal at every request:

Started GET "/assets/application.css" for 10.0.2.2 at 2012-12-13 21:33:05 +0000
Served asset /application.css - 304 Not Modified (17ms)
cache: [GET /assets/application.js] stale, valid, storecode>

These extraneous log messages are reduced to just the asset manifests by turning asset debugging off, but you can minimize them even further to de-clutter the development server log. The discussion of Rails bug 2639 offers several approaches, but the easiest is simply adding the newly released disable_assets_logger gem to your Gemfile:

gem "disable_assets_logger", "> 1.0.0", group: :development

The cache-related log lines will still appear, but the other lines are exiled to/dev/null.

Precompiling assets

Disabling asset debugging still requires that assets be compiled for each request.  I consider that a good thing in general, but some developers find a speed advantage in the development environment by precompiling assets:

$ RAILS_ENV=development bundle exec rake assets:precompile

However, be careful not to commit your precompiled assets to source control (unless that’s part of your dev process) and remember that changes to stylesheets and Javascript code won’t be reflected in page reloads until you manually recompile in the changes.  Supposedly you can also remove the precompiled files with either of these lines:

$ rake assets:clean
$ rm -r public/assets

but in practice I’ve had to ferret out precompiled files from caches and tmp directories, which outweighs any speed savings.

Development gems

There are also a few gems available that purport to speed up the request process in the development environment, although in my brief experiments with them they haven’t provided enough of a speed advantage to make up for any inherent disadvantages, additional code requirements, or configuration time.

  1. rails-dev-boost: reduces the frequency with which Ruby files are reloaded in response to requests
  2. rails-dev-tweaks: prevents asset requests from reloading Ruby files

+ more