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 subfoldersrequire_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
| Task | Command |
|---|---|
| Precompile assets for production | rails assets:precompile |
| Clean compiled assets | rails 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.
