Overview
The Asset Pipeline processes static files through a compilation system that transforms, combines, and optimizes assets for web delivery. Rails implements this through the Sprockets gem, which provides a Rack-based asset server and compilation environment.
The pipeline operates through three primary stages: preprocessing, concatenation, and compression. During preprocessing, assets written in languages like SCSS, CoffeeScript, or ERB get compiled to their web-ready equivalents. Concatenation combines multiple files to reduce HTTP requests. Compression minifies the resulting files to decrease transfer sizes.
Rails organizes assets in specific directory structures. The app/assets
directory contains application-specific assets, while lib/assets
holds library code and vendor/assets
stores third-party assets. The pipeline searches these paths when resolving asset references.
# config/application.rb
config.assets.paths << Rails.root.join('app', 'assets', 'fonts')
config.assets.precompile += %w( admin.css admin.js )
Asset fingerprinting creates unique filenames based on file content, enabling aggressive caching strategies. When file content changes, the filename changes, forcing browsers to fetch the updated version.
# Development: application.css
# Production: application-a1b2c3d4e5f6.css
Rails.application.assets.find_asset('application.css').digest_path
The pipeline integrates with Rails helpers that generate appropriate HTML tags. These helpers automatically include fingerprinted filenames and handle asset path resolution.
# In views
stylesheet_link_tag 'application'
# Generates: <link rel="stylesheet" href="/assets/application-digest.css">
javascript_include_tag 'application'
# Generates: <script src="/assets/application-digest.js"></script>
Basic Usage
Asset Pipeline configuration occurs primarily in environment files and the application configuration. The pipeline operates differently between development and production environments to optimize the development experience while ensuring production performance.
In development, the pipeline compiles assets on demand. This allows immediate feedback when modifying stylesheets or JavaScript files. The development server intercepts requests for assets and compiles them if they don't exist or have been modified.
# config/environments/development.rb
config.assets.debug = true
config.assets.digest = false
config.assets.raise_runtime_errors = true
Production environments require asset precompilation before deployment. The rails assets:precompile
task generates compiled assets with fingerprinted filenames and writes them to the public/assets
directory.
# config/environments/production.rb
config.assets.compile = false
config.assets.digest = true
config.assets.compress = true
Manifest files define asset dependencies and compilation targets. The application manifest typically resides in app/assets/stylesheets/application.css
and app/assets/javascripts/application.js
.
/*
*= require_tree .
*= require_self
*/
/* CSS rules follow */
body { margin: 0; }
//= require jquery
//= require jquery_ujs
//= require_tree .
// JavaScript code follows
$(document).ready(function() {
console.log('Application loaded');
});
The require_tree
directive includes all files in the current directory and subdirectories. The require_self
directive includes the current file's content. Specific files can be included using require filename
without the extension.
Asset helpers provide path resolution and HTML generation. These helpers respect the current environment's configuration and handle fingerprinting automatically.
asset_path('application.css')
# Development: "/assets/application.css"
# Production: "/assets/application-a1b2c3d4.css"
asset_url('logo.png')
# Returns full URL including protocol and host
Custom preprocessors can be added to handle specialized file types. The pipeline uses file extensions to determine which preprocessors to apply.
# config/application.rb
config.assets.configure do |env|
env.register_mime_type 'text/custom', extensions: ['.custom']
env.register_preprocessor 'text/custom', CustomProcessor
end
Environment-specific asset configurations handle different deployment requirements. Test environments often disable compilation for faster test execution, while staging environments may mirror production settings.
Production Patterns
Production deployment requires careful asset pipeline configuration to ensure optimal performance and reliability. The compilation process generates static files that web servers can deliver efficiently without invoking the Rails application.
Precompilation typically occurs during the deployment process, often as part of a build pipeline or deployment script. The compilation process reads source assets, applies transformations, and writes optimized files to the public directory.
# Deployment script
RAILS_ENV=production bundle exec rails assets:precompile
# config/environments/production.rb
config.assets.compile = false
config.assets.digest = true
config.assets.js_compressor = :terser
config.assets.css_compressor = :sass
Web server configuration serves precompiled assets directly, bypassing the Rails application entirely. Nginx and Apache can deliver static files more efficiently than application servers.
# nginx.conf
location ~ ^/(assets|images|javascripts|stylesheets|system)/ {
expires 1y;
add_header Cache-Control public;
add_header ETag "";
break;
}
CDN integration requires proper asset host configuration. The asset pipeline generates URLs pointing to the CDN rather than the application server.
# config/environments/production.rb
config.action_controller.asset_host = 'https://cdn.example.com'
Error handling during compilation prevents failed deployments. The precompilation task exits with a non-zero status when compilation fails, allowing deployment scripts to detect problems.
# Custom compilation task
namespace :assets do
task :precompile_with_fallback do
begin
Rake::Task['assets:precompile'].invoke
rescue StandardError => e
Rails.logger.error "Asset compilation failed: #{e.message}"
raise
end
end
end
Asset versioning strategies handle cache invalidation across deployments. The fingerprinting system automatically handles individual file changes, but application-wide asset changes may require additional cache busting.
# config/application.rb
config.assets.version = ENV['DEPLOYMENT_VERSION'] || '1.0'
Deployment verification ensures assets compiled correctly and are accessible. Health checks can verify critical assets exist and load properly.
# Health check endpoint
def assets_health
critical_assets = ['application.css', 'application.js']
missing_assets = critical_assets.reject do |asset|
Rails.application.assets.find_asset(asset)
end
if missing_assets.empty?
render json: { status: 'ok' }
else
render json: { status: 'error', missing: missing_assets }, status: 500
end
end
Zero-downtime deployments require careful coordination between asset compilation and application deployment. Strategies like symlinked releases ensure new assets are available before the application switches to use them.
# Capistrano deployment
before 'deploy:symlink:release', 'deploy:compile_assets'
after 'deploy:publishing', 'deploy:cleanup_assets'
Performance & Memory
Asset Pipeline performance directly impacts application load times and server resource consumption. Optimization strategies focus on reducing compilation time, minimizing asset sizes, and efficient caching.
Compilation performance depends on asset complexity and dependency trees. Complex SCSS files with deep nesting and extensive imports require more processing time. Monitoring compilation duration helps identify bottlenecks.
# Measure compilation time
def time_asset_compilation
start_time = Time.current
Rails.application.assets.find_asset('application.css')
compilation_time = Time.current - start_time
Rails.logger.info "Asset compilation took #{compilation_time}s"
end
Memory consumption during compilation can become significant with large asset sets. The pipeline loads entire dependency trees into memory, which may exceed available memory on constrained systems.
# Monitor memory usage during compilation
require 'objspace'
ObjectSpace.trace_object_allocations_start
Rails.application.assets.find_asset('application.css')
allocations = ObjectSpace.trace_object_allocations_stop
Rails.logger.info "Objects allocated: #{allocations}"
Caching strategies reduce redundant compilation work. The pipeline maintains internal caches that persist compiled results between requests in development and across compilation runs in production.
# config/environments/development.rb
config.assets.cache_store = :file_store, Rails.root.join('tmp', 'cache', 'assets')
File watching in development environments triggers recompilation when source files change. Efficient file watching reduces CPU overhead while maintaining responsive asset updates.
# config/environments/development.rb
config.assets.logger = Logger.new('/dev/null') # Reduce log noise
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
Asset size optimization reduces transfer times and bandwidth consumption. The pipeline provides multiple compression strategies for different asset types.
# config/environments/production.rb
config.assets.js_compressor = Terser.new(
compress: {
drop_console: true,
drop_debugger: true
}
)
config.assets.css_compressor = SassC::Compressor.new(
style: :compressed
)
Selective compilation prevents processing unused assets. The precompile array specifies which assets to compile, avoiding unnecessary work on unused files.
# config/application.rb
config.assets.precompile = %w[
application.css
application.js
admin/application.css
admin/application.js
]
Parallel compilation can reduce total compilation time on multi-core systems. However, this increases memory usage as multiple compilation processes run simultaneously.
# Custom parallel compilation
require 'parallel'
assets_to_compile = %w[application.css admin.css mobile.css]
Parallel.each(assets_to_compile, in_threads: 4) do |asset_name|
Rails.application.assets.find_asset(asset_name)
end
Profile-guided optimization identifies expensive operations within the compilation process. Profiling tools can reveal which preprocessors or assets consume the most resources.
# Profile asset compilation
require 'ruby-prof'
RubyProf.start
Rails.application.assets.find_asset('application.css')
result = RubyProf.stop
File.open('compilation_profile.html', 'w') do |file|
RubyProf::GraphHtmlPrinter.new(result).print(file)
end
Reference
Configuration Options
Option | Type | Default | Description |
---|---|---|---|
config.assets.enabled |
Boolean | true |
Enable/disable asset pipeline |
config.assets.paths |
Array | [] |
Additional asset load paths |
config.assets.precompile |
Array | %w[application.css application.js] |
Assets to precompile |
config.assets.prefix |
String | "/assets" |
URL prefix for assets |
config.assets.digest |
Boolean | true in production |
Enable asset fingerprinting |
config.assets.debug |
Boolean | true in development |
Concatenate assets or serve individually |
config.assets.compile |
Boolean | true in development |
Compile assets on demand |
config.assets.compress |
Boolean | true in production |
Enable asset compression |
config.assets.css_compressor |
Symbol/Object | nil |
CSS compression engine |
config.assets.js_compressor |
Symbol/Object | nil |
JavaScript compression engine |
config.assets.gzip |
Boolean | true |
Generate gzipped versions |
config.assets.logger |
Logger | Rails.logger |
Asset pipeline logger |
config.assets.cache_store |
Symbol/Object | Default cache store | Asset compilation cache |
config.assets.version |
String | "1.0" |
Asset version for cache busting |
Asset Helper Methods
Method | Parameters | Returns | Description |
---|---|---|---|
asset_path(source, **options) |
source (String), options (Hash) |
String |
Returns asset path |
asset_url(source, **options) |
source (String), options (Hash) |
String |
Returns full asset URL |
stylesheet_link_tag(*sources, **options) |
sources (Array), options (Hash) |
String |
Generates CSS link tags |
javascript_include_tag(*sources, **options) |
sources (Array), options (Hash) |
String |
Generates JS script tags |
image_tag(source, **options) |
source (String), options (Hash) |
String |
Generates image tags |
audio_tag(source, **options) |
source (String), options (Hash) |
String |
Generates audio tags |
video_tag(source, **options) |
source (String), options (Hash) |
String |
Generates video tags |
Manifest Directives
Directive | Usage | Description |
---|---|---|
require |
//= require filename |
Include specific file |
require_directory |
//= require_directory path |
Include files in directory (non-recursive) |
require_tree |
//= require_tree path |
Include files in directory tree (recursive) |
require_self |
//= require_self |
Include current file content |
stub |
//= stub filename |
Exclude file from compilation |
depend_on |
//= depend_on filename |
Mark dependency without inclusion |
depend_on_asset |
//= depend_on_asset filename |
Mark asset dependency |
Compression Engines
Engine | Type | Configuration |
---|---|---|
:terser |
JavaScript | config.assets.js_compressor = :terser |
:closure |
JavaScript | config.assets.js_compressor = :closure |
:yui |
JavaScript | config.assets.js_compressor = :yui |
:sass |
CSS | config.assets.css_compressor = :sass |
:yui |
CSS | config.assets.css_compressor = :yui |
File Extension Processing
Extension | Processor | Output Format |
---|---|---|
.scss |
Sass | CSS |
.sass |
Sass | CSS |
.less |
Less | CSS |
.coffee |
CoffeeScript | JavaScript |
.ts |
TypeScript | JavaScript |
.erb |
ERB | Original format |
.slim |
Slim | HTML |
.haml |
Haml | HTML |
Rake Tasks
Task | Description |
---|---|
rails assets:precompile |
Compile all assets for production |
rails assets:clean |
Remove compiled assets |
rails assets:clobber |
Remove all compiled assets and cache |
rails assets:environment |
Load asset environment |
Environment Variables
Variable | Description | Example |
---|---|---|
RAILS_ASSETS_CACHE_PATH |
Asset cache directory | /tmp/cache/assets |
RAILS_ASSETS_QUIET |
Suppress asset logs | true |
SECRET_KEY_BASE |
Required for asset compilation | abc123... |
Common MIME Types
Extension | MIME Type | Processing |
---|---|---|
.css |
text/css |
CSS processing |
.js |
application/javascript |
JavaScript processing |
.png |
image/png |
Image optimization |
.jpg |
image/jpeg |
Image optimization |
.gif |
image/gif |
Image optimization |
.svg |
image/svg+xml |
SVG optimization |
.woff |
font/woff |
Font serving |
.ttf |
font/ttf |
Font serving |