Secrets of the asset pipeline

43
Secrets Of The Asset Pipeline Ken Collins metaskills.net Sunday, December 18, 11

description

Following up from my recent deep code dive into the less-rails and less-rails-bootstrap gems come some of the best hidden features of the rails asset pipeline. My talk will include a behind the scenes look of what makes the asset pipeline possible, best practices, advanced usage followed by a review of some of the top level CSS frameworks being used.

Transcript of Secrets of the asset pipeline

Page 1: Secrets of the asset pipeline

Secrets Of The Asset Pipeline

Ken Collinsmetaskills.net

Sunday, December 18, 11

Page 2: Secrets of the asset pipeline

The FoundationWhat makes the asset pipeline possible.

Sunday, December 18, 11

Page 3: Secrets of the asset pipeline

Hike

Sunday, December 18, 11

Page 4: Secrets of the asset pipeline

HikeHike is a Ruby library for

!nding !les in a set of paths. Use it to implement search

paths, load paths, and the like.

Sunday, December 18, 11

Page 5: Secrets of the asset pipeline

Find Ruby Files In Your Project

trail = Hike::Trail.new "/Users/sam/Projects/hike"trail.append_extension ".rb"trail.append_paths "lib", "test"

trail.find "hike/trail"# => "/Users/sam/Projects/hike/lib/hike/trail.rb"

trail.find "test_trail"# => "/Users/sam/Projects/hike/test/test_trail.rb"

Sunday, December 18, 11

Page 6: Secrets of the asset pipeline

Explore Your Shell Path

trail = Hike::Trail.new "/"trail.append_paths *ENV["PATH"].split(":")

trail.find "ls"# => "/bin/ls"

trail.find "gem"# => "/Users/sam/.rvm/rubies/ree/bin/gem"

Sunday, December 18, 11

Page 7: Secrets of the asset pipeline

Digging Deeper# Fallback logical paths. Equivalent.trail.find "hike", "hike/index"trail.find("hike") || trail.find("hike/index")

# Block yields multiple matches.trail.find("application") do |path| return path if mime_type_for(path) == "text/css"end

# Like Dir#entries. Filters "." and "~" swap files.trail.entries('/usr/local/bin')

# Like File.stat.trail.stat('/usr/local/bin')

# Cached trail. Avoids excess system calls.trail.index

Sunday, December 18, 11

Page 8: Secrets of the asset pipeline

Tilt

Sunday, December 18, 11

Page 9: Secrets of the asset pipeline

TiltTilt is a thin interface over a bunch of

different Ruby template engines in an attempt to make their usage as generic possible. is is

useful for web frameworks, static site generators, and other systems that support

multiple template engines but don't want to code for each of them individually.

Sunday, December 18, 11

Page 10: Secrets of the asset pipeline

Common Features

Sunday, December 18, 11

Page 11: Secrets of the asset pipeline

Common FeaturesCustom template evaluation scopes / bindings.

Sunday, December 18, 11

Page 12: Secrets of the asset pipeline

Common FeaturesCustom template evaluation scopes / bindings.Ability to pass locals to template evaluation.

Sunday, December 18, 11

Page 13: Secrets of the asset pipeline

Common FeaturesCustom template evaluation scopes / bindings.Ability to pass locals to template evaluation.Support for passing a block to template eval for "yield".

Sunday, December 18, 11

Page 14: Secrets of the asset pipeline

Common FeaturesCustom template evaluation scopes / bindings.Ability to pass locals to template evaluation.Support for passing a block to template eval for "yield".Backtraces with correct filenames and line numbers.

Sunday, December 18, 11

Page 15: Secrets of the asset pipeline

Common FeaturesCustom template evaluation scopes / bindings.Ability to pass locals to template evaluation.Support for passing a block to template eval for "yield".Backtraces with correct filenames and line numbers.Template file caching and reloading.

Sunday, December 18, 11

Page 16: Secrets of the asset pipeline

Common FeaturesCustom template evaluation scopes / bindings.Ability to pass locals to template evaluation.Support for passing a block to template eval for "yield".Backtraces with correct filenames and line numbers.Template file caching and reloading.Fast, method-based template source compilation.

Sunday, December 18, 11

Page 17: Secrets of the asset pipeline

Engine File Extension Required Lib.ERB .erb, .rhtml none (stdlib)

Interpolated String .str none (core)

Erubis .erb, .rhtml, .erubis erubis

Haml .haml haml

Sass .sass sass (>= 3.1)

Scss .scss sass (>= 3.1)

Less CSS .less less

Builder .builder builder

Liquid .liquid liquid

RDiscount .markdown, .mkd, .md rdiscount

Redcarpet .markdown, .mkd, .md redcarpet

BlueCloth .markdown, .mkd, .md bluecloth

Kramdown .markdown, .mkd, .md kramdown

Maruku .markdown, .mkd, .md maruku

RedCloth .textile redcloth

RDoc .rdoc rdoc

Radius .radius radius

Markaby .mab markaby

Nokogiri .nokogiri nokogiri

CoffeeScript .coffee coffee-script (+javascript)

Creole (Wiki markup) .wiki, .creole creole

WikiCloth (Wiki markup) .wiki, .mediawiki, .mw wikicloth

Yajl .yajl yajl-ruby

Sunday, December 18, 11

Page 18: Secrets of the asset pipeline

Engine File Extension Required Lib.ERB .erb, .rhtml none (stdlib)

Interpolated String .str none (core)

Erubis .erb, .rhtml, .erubis erubis

Haml .haml haml

Sass .sass sass (>= 3.1)

Scss .scss sass (>= 3.1)

Less CSS .less less

Builder .builder builder

Liquid .liquid liquid

RDiscount .markdown, .mkd, .md rdiscount

Redcarpet .markdown, .mkd, .md redcarpet

BlueCloth .markdown, .mkd, .md bluecloth

Kramdown .markdown, .mkd, .md kramdown

Maruku .markdown, .mkd, .md maruku

RedCloth .textile redcloth

RDoc .rdoc rdoc

Radius .radius radius

Markaby .mab markaby

Nokogiri .nokogiri nokogiri

CoffeeScript .coffee coffee-script (+javascript)

Creole (Wiki markup) .wiki, .creole creole

WikiCloth (Wiki markup) .wiki, .mediawiki, .mw wikicloth

Yajl .yajl yajl-ruby

Sunday, December 18, 11

Page 19: Secrets of the asset pipeline

Really Simple!

require 'erb'require 'tilt'

template = Tilt.new('templates/foo.erb') #<Tilt::ERBTemplate @file="templates/foo.rb"...>

template.render # => "Hello world!"

Sunday, December 18, 11

Page 20: Secrets of the asset pipeline

Evaluation Scope

template = Tilt::ERBTemplate.new('templates/foo.erb')joe = Person.find('joe')output = template.render(joe, :x => 35, :y => 42)

jane = Person.find('jane')output = template.render(jane, :x => 22, :y => nil)

Sunday, December 18, 11

Page 21: Secrets of the asset pipeline

Sprockets

Sunday, December 18, 11

Page 22: Secrets of the asset pipeline

SprocketsRack-based asset packaging for compiling

and serving web assets. It features declarative dependency management for

JavaScript and CSS assets, as well as a powerful preprocessor pipeline that allows

you to write assets in languages like CoffeeScript, Sass, SCSS and LESS.

Sunday, December 18, 11

Page 23: Secrets of the asset pipeline

Rack Application# In config.ru

require 'sprockets'

map '/assets' do environment = Sprockets::Environment.new environment.append_path 'app/assets/javascripts' environment.append_path 'app/assets/stylesheets' run environmentend

map '/' do run YourRackAppend

Sunday, December 18, 11

Page 24: Secrets of the asset pipeline

Renders Templates

/* Multi-line comment blocks (CSS, SCSS, JavaScript) *= require foo */

// Single-line comment blocks (SCSS, JavaScript)//= require foo

# Single-line comment blocks (CoffeeScript)#= require foo

modal.css.scss.erb

Sunday, December 18, 11

Page 25: Secrets of the asset pipeline

Best PracticesHow to wire it up right!

Sunday, December 18, 11

Page 26: Secrets of the asset pipeline

Dir. Structure $ tree app/assets |!"" images#   !"" app#   #   !"" ...#   $"" site#   $"" ...!"" javascripts#   !"" application.js#   | $"" ...#   !"" shared#   #   !"" base.js.coffee#   #   !"" modal.js.coffee.erb#   #   $"" ...#   !"" site| | !"" base.js.coffee#   | !"" flash.js.coffee#   | $"" ...| $"" site.js$"" stylesheets !"" application #   $"" application.css.scss !"" application.css !"" shared #   !"" base.scss #   !"" modal.css.scss #   $"" ... !"" site #   !"" 960.css #   $"" site.css.scss $"" site.css

Sunday, December 18, 11

Page 27: Secrets of the asset pipeline

Dir. Structure $ tree app/assets |!"" images#   !"" app#   #   !"" ...#   $"" site#   $"" ...!"" javascripts#   !"" application.js#   | $"" ...#   !"" shared#   #   !"" base.js.coffee#   #   !"" modal.js.coffee.erb#   #   $"" ...#   !"" site| | !"" base.js.coffee#   | !"" flash.js.coffee#   | $"" ...| $"" site.js$"" stylesheets !"" application #   $"" application.css.scss !"" application.css !"" shared #   !"" base.scss #   !"" modal.css.scss #   $"" ... !"" site #   !"" 960.css #   $"" site.css.scss $"" site.css

Directory Namespaces

Sunday, December 18, 11

Page 28: Secrets of the asset pipeline

Dir. Structure $ tree app/assets |!"" images#   !"" app#   #   !"" ...#   $"" site#   $"" ...!"" javascripts#   !"" application.js#   | $"" ...#   !"" shared#   #   !"" base.js.coffee#   #   !"" modal.js.coffee.erb#   #   $"" ...#   !"" site| | !"" base.js.coffee#   | !"" flash.js.coffee#   | $"" ...| $"" site.js$"" stylesheets !"" application #   $"" application.css.scss !"" application.css !"" shared #   !"" base.scss #   !"" modal.css.scss #   $"" ... !"" site #   !"" 960.css #   $"" site.css.scss $"" site.css

Directory NamespacesManifest Only Top Files

Sunday, December 18, 11

Page 29: Secrets of the asset pipeline

Dir. Structure $ tree app/assets |!"" images#   !"" app#   #   !"" ...#   $"" site#   $"" ...!"" javascripts#   !"" application.js#   | $"" ...#   !"" shared#   #   !"" base.js.coffee#   #   !"" modal.js.coffee.erb#   #   $"" ...#   !"" site| | !"" base.js.coffee#   | !"" flash.js.coffee#   | $"" ...| $"" site.js$"" stylesheets !"" application #   $"" application.css.scss !"" application.css !"" shared #   !"" base.scss #   !"" modal.css.scss #   $"" ... !"" site #   !"" 960.css #   $"" site.css.scss $"" site.css

Directory NamespacesManifest Only Top Files Generators Garbage

Sunday, December 18, 11

Page 30: Secrets of the asset pipeline

Dir. Structure $ tree app/assets |!"" images#   !"" app#   #   !"" ...#   $"" site#   $"" ...!"" javascripts#   !"" application.js#   | $"" ...#   !"" shared#   #   !"" base.js.coffee#   #   !"" modal.js.coffee.erb#   #   $"" ...#   !"" site| | !"" base.js.coffee#   | !"" flash.js.coffee#   | $"" ...| $"" site.js$"" stylesheets !"" application #   $"" application.css.scss !"" application.css !"" shared #   !"" base.scss #   !"" modal.css.scss #   $"" ... !"" site #   !"" 960.css #   $"" site.css.scss $"" site.css

Directory NamespacesManifest Only Top Files Generators GarbageRequire Tree Bad

Sunday, December 18, 11

Page 31: Secrets of the asset pipeline

Dir. Structure $ tree app/assets |!"" images#   !"" app#   #   !"" ...#   $"" site#   $"" ...!"" javascripts#   !"" application.js#   | $"" ...#   !"" shared#   #   !"" base.js.coffee#   #   !"" modal.js.coffee.erb#   #   $"" ...#   !"" site| | !"" base.js.coffee#   | !"" flash.js.coffee#   | $"" ...| $"" site.js$"" stylesheets !"" application #   $"" application.css.scss !"" application.css !"" shared #   !"" base.scss #   !"" modal.css.scss #   $"" ... !"" site #   !"" 960.css #   $"" site.css.scss $"" site.css

Directory NamespacesManifest Only Top Files Generators GarbageRequire Tree BadTry To Match With Layout Names

Sunday, December 18, 11

Page 32: Secrets of the asset pipeline

site.js

//= require jquery-1.6.2.min//= require jquery-ui-1.8.12.ui-darkness.min//= require jquery_ujs//= require shared/base//= require shared/utils//= require shared/modal//= require shared/spinner//= require site/quickie//= require site/flash//= require site/site

Sunday, December 18, 11

Page 33: Secrets of the asset pipeline

site.css

/* *= require application/application *= require shared/modal *= require shared/utility*/

Sunday, December 18, 11

Page 34: Secrets of the asset pipeline

Precompile Additional Assets!

# Precompile additional assets # (application.js, application.css, # and all non-JS/CSS are already added)config.assets.precompile += ['site.js', 'site.css']

config/production.rb

Sunday, December 18, 11

Page 35: Secrets of the asset pipeline

Dir. Structure $ tree app/assets |!"" images#   !"" app#   #   !"" ...#   $"" site#   $"" ...!"" javascripts#   !"" application.js#   | $"" ...#   !"" shared#   #   !"" base.js.coffee#   #   !"" modal.js.coffee.erb#   #   $"" ...#   !"" site| | !"" base.js.coffee#   | !"" flash.js.coffee#   | $"" ...| $"" site.js$"" stylesheets !"" application #   $"" application.css.scss !"" application.css !"" shared #   !"" base.scss #   !"" modal.css.scss #   $"" ... !"" site #   !"" 960.css #   $"" site.css.scss $"" site.css

Directory NamespacesManifest Only Top Files Generators GarbageRequire Tree BadTry To Match With Layout Names

Sunday, December 18, 11

Page 36: Secrets of the asset pipeline

Dir. Structure $ tree app/assets |!"" images#   !"" app#   #   !"" ...#   $"" site#   $"" ...!"" javascripts#   !"" application.js#   | $"" ...#   !"" shared#   #   !"" base.js.coffee#   #   !"" modal.js.coffee.erb#   #   $"" ...#   !"" site| | !"" base.js.coffee#   | !"" flash.js.coffee#   | $"" ...| $"" site.js$"" stylesheets !"" application #   $"" application.css.scss !"" application.css !"" shared #   !"" base.scss #   !"" modal.css.scss #   $"" ... !"" site #   !"" 960.css #   $"" site.css.scss $"" site.css

Directory NamespacesManifest Only Top Files Generators GarbageRequire Tree BadTry To Match With Layout Names

Sub Files @import’ed

Sunday, December 18, 11

Page 37: Secrets of the asset pipeline

Dir. Structure $ tree app/assets |!"" images#   !"" app#   #   !"" ...#   $"" site#   $"" ...!"" javascripts#   !"" application.js#   | $"" ...#   !"" shared#   #   !"" base.js.coffee#   #   !"" modal.js.coffee.erb#   #   $"" ...#   !"" site| | !"" base.js.coffee#   | !"" flash.js.coffee#   | $"" ...| $"" site.js$"" stylesheets !"" application #   $"" application.css.scss !"" application.css !"" shared #   !"" base.scss #   !"" modal.css.scss #   $"" ... !"" site #   !"" 960.css #   $"" site.css.scss $"" site.css

Directory NamespacesManifest Only Top Files Generators GarbageRequire Tree BadTry To Match With Layout Names

Sub Files @import’edBase Files Are Your Compass

Sunday, December 18, 11

Page 38: Secrets of the asset pipeline

Base Files Are Your Compass

$legacy-support-for-ie: false;$experimental-support-for-opera: false;$experimental-support-for-khtml: false;@import "compass";@import "compass/layout";

app/assets/stylesheets/shared/base.scss

/* *= depend_on shared/base.scss */@import "shared/base";

app/assets/stylesheets/shared/modal.scss

Sunday, December 18, 11

Page 39: Secrets of the asset pipeline

Advanced UsageSecrets of the asset pipeline.

Sunday, December 18, 11

Page 40: Secrets of the asset pipeline

Hooking Into SprocketsRails.application.assets# => #<Sprockets::Environment:0x3fda9a195f8c root="/Repos/homemarks_app", paths=["/Repos/homemarks_app/app/assets/images", "/Repos/homemarks_app/app/assets/javascripts", "/Repos/homemarks_app/app/assets/stylesheets", "/Repos/homemarks_app/vendor/assets/javascripts", "/Repos/homemarks_app/vendor/assets/stylesheets", "/Users/ken/.rbenv/versions/1.9.3/lib/ruby/gems/1.9.1/gems/jquery-rails-1.0.13/vendor/assets/javascripts"], digest="46dde6621c301f4928e3b34efee9e3b5">

Or use the `asset_environment` helper.

Sunday, December 18, 11

Page 41: Secrets of the asset pipeline

Finding Assets

Rails.application.assets['shared/modal']# => #<Sprockets::BundledAsset:0x3fcd7e90c6cc pathname="/Repos/homemarks_app/app/assets/javascripts/shared/modal.js.coffee.erb", mtime=2011-11-25 17:41:11 -0500, digest="775822db3e101bf38d7978627380e62b">

#find_asset method (aliased as [])

Sunday, December 18, 11

Page 42: Secrets of the asset pipeline

* Advanced Usage - Where is sprockets. > Rails.application.assets (helpers can use asset_environment) - Finding Assets. #find_asset method (aliased as []) Rails.application.assets['shared/modal'] # => Sprockets::BundledAsset Call to_s on the resulting asset to access its contents, length to get its length in bytes, mtime to query its last-modified time, and pathname to get its full path on the filesystem. - Asset Helpers. - image, asset-data-uri, etc. Move all images to app/assets!!! Rails.application.assets['site/hmlogo.png'] # => #<Sprockets::StaticAsset:0x3fda99465d08 pathname="/Users/kencollins/Repositories/homemarks_app/app/assets/images/site/hmlogo.png", mtime=2011-11-16 19:31:44 -0500, digest="eed9e6f3fd9fa546ccd7ce49edd99f49"> - Custom SASS - Preprocessors. - Assets in other assets. - Precompiling. Fingerprints. When they are used. - JavaScript Templating with EJS and Eco (read sprockets page) - JST (define) - EJS or Eco - CSS Compressors (:uglifier default, but use :yui for both css/js) group :assets do # ... gem 'yui-compressor', :require => 'yui/compressor' end - Your config/application.rb if defined?(Bundler) # If you precompile assets before deploying to production, use this line Bundler.require *Rails.groups(:assets => %w(development test)) # If you want your assets lazily compiled in production, use this line # Bundler.require(:default, :assets, Rails.env) end

* CSS Frameworks. - Less - Stylus - Sass - http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#each-directive - http://github.com/kuroir/SCSS.tmbundle - Compass - mate "$(bundle show compass)/frameworks/compass/stylesheets"

Incomplete Notes

Sunday, December 18, 11

Page 43: Secrets of the asset pipeline

Thanks!Ken Collins

metaskills.net

Sunday, December 18, 11