RoR Asset Pipeline

The asset pipeline is the system Rails uses to manage, process, and serve CSS, JavaScript, and image files. It combines multiple files into one, compresses them, and adds fingerprints to filenames so browsers cache them correctly. The result is faster page loads and more organized front-end code.

What the Asset Pipeline Does

Development Environment:
  Many small CSS and JS files → served individually for easy debugging

Production Environment:
  Many small CSS and JS files
        |
        v
  Asset Pipeline processes them:
  - Combines all CSS into one file
  - Combines all JS into one file
  - Compresses (minifies) both
  - Adds a fingerprint to the filename for cache busting
        |
        v
  Browser downloads one small CSS file and one small JS file
  → Faster page load

Asset Folder Structure

app/assets/
  +-- stylesheets/
  |     application.css       ← main CSS manifest
  |     components/
  |       header.css
  |       footer.css
  |       cards.css
  |
  +-- javascript/
  |     application.js        ← main JS manifest
  |
  +-- images/
        logo.png
        banner.jpg
        icons/
          star.svg

The Manifest Files

Manifest files tell the asset pipeline which files to include and in what order.

app/assets/stylesheets/application.css

/*
 *= require_tree .
 *= require_self
 */
  • require_tree . — includes all CSS files in this folder and subfolders
  • require_self — includes any CSS written directly in this file
app/assets/javascript/application.js (importmap style, Rails 7+)

import "@hotwired/turbo-rails"
import "controllers"

Linking Assets in Views

Never link to asset files directly with a plain HTML path. Use Rails helpers so the pipeline can fingerprint and serve them correctly:

CSS:
  <%= stylesheet_link_tag "application" %>
  Renders: <link rel="stylesheet" href="/assets/application-abc123.css">

JavaScript:
  <%= javascript_include_tag "application" %>
  Renders: <script src="/assets/application-xyz789.js"></script>

Images:
  <%= image_tag "logo.png" %>
  Renders: <img src="/assets/logo-def456.png">

In CSS (referencing images):
  background-image: url(image-path("banner.jpg"));

Image URL in Ruby code:
  <%= image_path("logo.png") %>
  Returns: "/assets/logo-def456.png"

Fingerprinting and Cache Busting

When the asset pipeline compiles assets, it adds a hash of the file's contents to the filename:

application.css      →  application-abc123def456.css
application.js       →  application-xyz789ghi012.js
logo.png             →  logo-jkl345mno678.png

When you change the file, the hash changes, so the filename changes. Browsers that cached the old file automatically download the new one because the filename is different. This is cache busting without manual version numbers.

Adding External CSS Frameworks

To add a CSS framework like Bootstrap, include it via a CDN in your layout, or install it via a gem or npm package.

Via CDN (simplest):
In app/views/layouts/application.html.erb <head>:
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">

Via gem (add to Gemfile):
  gem "bootstrap", "~> 5.3"
  Then run: bundle install
  Then import in application.scss: @import "bootstrap";

Sass / SCSS Support

Rename your CSS files to .scss to use SCSS syntax. SCSS lets you use variables, nesting, and mixins:

app/assets/stylesheets/application.scss

$primary-color: #3a86ff;
$font-size-base: 16px;

body {
  font-size: $font-size-base;
  color: #333;
}

nav {
  background: $primary-color;

  a {
    color: white;
    text-decoration: none;

    &:hover {
      text-decoration: underline;
    }
  }
}

Precompiling Assets for Production

Before deploying to production, compile your assets:

RAILS_ENV=production rails assets:precompile

This generates the compressed, fingerprinted asset files in public/assets/. Your server then serves these static files directly without running Rails for every CSS or JS request.

Asset Pipeline in Rails 7 — Importmaps

Rails 7 introduced Importmaps as the default JavaScript approach. It serves JavaScript files directly to modern browsers without bundling or transpiling:

config/importmap.rb

pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "controllers", to: "controllers/index.js", preload: true

Importmaps work well for most Rails applications. For complex JavaScript setups (React, Vue), use jsbundling-rails with esbuild or webpack instead.

Common Asset Pipeline Tasks

TaskCommand
Precompile assets for productionrails assets:precompile
Clean compiled assetsrails assets:clobber
Add a new JS package (importmap)bin/importmap pin lodash
Remove a JS package (importmap)bin/importmap unpin lodash

The asset pipeline handles the tedious parts of front-end optimization automatically. You write normal CSS and JavaScript, and Rails takes care of combining, compressing, and serving them efficiently.

Leave a Comment

Your email address will not be published. Required fields are marked *