Slide 1

Slide 1 text

Secrets Of The Asset Pipeline Ken Collins metaskills.net

Slide 2

Slide 2 text

Congratulations! The simple fact that you are sitting here listening to me, means you've made a glorious contribution to Science! Tragic, but informative. Cave Johnson

Slide 3

Slide 3 text

The Foundation What makes the asset pipeline possible.

Slide 4

Slide 4 text

Hike

Slide 5

Slide 5 text

Hike Hike is a Ruby library for finding files in a set of paths. Use it to implement search paths, load paths, and the like.

Slide 6

Slide 6 text

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"

Slide 7

Slide 7 text

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"

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

Tilt

Slide 10

Slide 10 text

Tilt Tilt is a thin interface over a bunch of different Ruby template engines in an attempt to make their usage as generic possible. This 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.

Slide 11

Slide 11 text

Common Features

Slide 12

Slide 12 text

Common Features Custom template evaluation scopes / bindings.

Slide 13

Slide 13 text

Common Features Custom template evaluation scopes / bindings. Ability to pass locals to template evaluation.

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

Common Features Custom 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.

Slide 16

Slide 16 text

Common Features Custom 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.

Slide 17

Slide 17 text

Common Features Custom 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.

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

Really Simple! require 'erb' require 'tilt' template = Tilt.new('templates/foo.erb') # template.render # => "Hello world!"

Slide 21

Slide 21 text

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)

Slide 22

Slide 22 text

Sprockets

Slide 23

Slide 23 text

Sprockets Rack-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.

Slide 24

Slide 24 text

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 environment end map '/' do run YourRackApp end

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

Best Practices How to wire it up right!

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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 Manifest Only Top Files

Slide 30

Slide 30 text

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 Manifest Only Top Files Generators Garbage

Slide 31

Slide 31 text

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 Manifest Only Top Files Generators Garbage Require Tree Bad

Slide 32

Slide 32 text

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 Manifest Only Top Files Generators Garbage Require Tree Bad Try To Match With Layout Names

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

site.css /* *= require application/application *= require shared/modal *= require shared/utility */

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

Do Not Use Minified Files # Compress both stylesheets and JavaScripts config.assets.js_compressor = :yui config.assets.css_compressor = :yui Gemfile group :assets do # ... gem 'yui-compressor', :require => 'yui/compressor' end config/production.rb

Slide 37

Slide 37 text

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 Manifest Only Top Files Generators Garbage Require Tree Bad Try To Match With Layout Names

Slide 38

Slide 38 text

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 Manifest Only Top Files Generators Garbage Require Tree Bad Try To Match With Layout Names Sub Files @import’ed

Slide 39

Slide 39 text

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 Manifest Only Top Files Generators Garbage Require Tree Bad Try To Match With Layout Names Sub Files @import’ed Base Files Are Your Compass

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

Advanced Usage Secrets of the asset pipeline.

Slide 42

Slide 42 text

LESS, Rails & Bootstrap less-rails.gem less-rails-bootstrap.gem

Slide 43

Slide 43 text

Too LESS? http://metaskills.net/2012/02/27/too-less-should-you-be-using-sass/

Slide 44

Slide 44 text

Too LESS?

Slide 45

Slide 45 text

Too LESS?

Slide 46

Slide 46 text

Too LESS?

Slide 47

Slide 47 text

sass-rails.gem https://github.com/rails/sass-rails

Slide 48

Slide 48 text

Railtie Configuration MyProject::Application.configure do config.sass.line_comments = false config.sass.style = :nested end In config/initializers/sass.rb

Slide 49

Slide 49 text

Asset Helpers!!! image-url("rails.png") /* Becomes: url(/assets/rails.png) */ font-url("rails.ttf") /* Becomes: url(/assets/rails.ttf) */ video-url("rails.mp4") /* Becomes: url(/videos/rails.mp4) */ audio-url("rails.mp3") /* Becomes: url(/audios/rails.mp3) */ javascript-url("rails.js") /* Becomes: url(/assets/rails.js) */ stylesheet-url("rails.css") /* Becomes: url(/assets/rails.css) */ asset-data-url("rails.png") /* Becomes: url(data:image/png;base64,iV...) */ In config/initializers/sass.rb

Slide 50

Slide 50 text

Keep /public Clean!

Slide 51

Slide 51 text

Very Extendable module Sass::Script::Functions def experimental_properties(value) assert_type value, :String prefixes = "-webkit-#{value}, -moz-#{value}, -ms-#{value}, #{value}" Sass::Script::String.new prefixes end declare :experimental_properties, [:value] end class Sass::Script::Color < Sass::Script::Literal def hsv_h rgb_to_hsv! @attrs[:hsv_h] end def hsv_s rgb_to_hsv! @attrs[:hsv_s] end def hsv_v rgb_to_hsv! @attrs[:hsv_v] end private def rgb_to_hsv! # ... end end

Slide 52

Slide 52 text

Compass CSS Framework http://compass-style.org/

Slide 53

Slide 53 text

compass-rails.gem https://github.com/Compass/compass-rails

Slide 54

Slide 54 text

Compass Extensions group :assets do gem 'compass-rails' gem 'compass-susy-plugin' gem 'ceaser-easing' end

Slide 55

Slide 55 text

Compass Extensions group :assets do gem 'compass-rails' gem 'compass-susy-plugin' gem 'ceaser-easing' end Susy - An un-obtrusive grid for designers.

Slide 56

Slide 56 text

Compass Extensions group :assets do gem 'compass-rails' gem 'compass-susy-plugin' gem 'ceaser-easing' end Susy - An un-obtrusive grid for designers. Ceaser Easing - Functions for CSS3 animations.

Slide 57

Slide 57 text

Learn the ways of the Force $ mate "$(bundle show compass)/frameworks/compass/stylesheets"

Slide 58

Slide 58 text

Twitter Bootstrap With Sass https://github.com/thomas-mcdonald/bootstrap-sass

Slide 59

Slide 59 text

Bootstrap Icon Fonts http://fortawesome.github.com/Font-Awesome/ https://github.com/littlebtc/font-awesome-sass-rails

Slide 60

Slide 60 text

Discreet jQuery UI Assets https://github.com/joliss/jquery-ui-rails

Slide 61

Slide 61 text

Discreet jQuery UI Assets /* *= require jquery.ui.core *= require jquery.ui.theme */ //= require jquery.ui.core //= require jquery.ui.widget //= require jquery.ui.mouse //= require jquery.ui.slider //= require jquery.ui.progressbar //= require jquery.effects.pulsate //= require jquery.effects.shake //= require jquery.effects.slide

Slide 62

Slide 62 text

Technical Tricks

Slide 63

Slide 63 text

Hooking Into Sprockets Rails.application.assets # => # Or use the `asset_environment` helper.

Slide 64

Slide 64 text

Finding Assets Rails.application.assets['shared/modal'] # => # #find_asset method (aliased as [])

Slide 65

Slide 65 text

Uses Of Assets _buildStyle: -> return unless @options.injectStyle style = $('') style.attr 'type', 'text/css' style.html <%= Rails.application.assets['shared/modal'].to_s %> $('head').append style Programmatically Use Assets

Slide 66

Slide 66 text

Uses Of Assets _buildStyle: -> return unless @options.injectStyle style = $('') style.attr 'type', 'text/css' style.html <%= Rails.application.assets['shared/modal'].to_s %> $('head').append style Programmatically Use Assets #to_s - Render Asset

Slide 67

Slide 67 text

Uses Of Assets _buildStyle: -> return unless @options.injectStyle style = $('') style.attr 'type', 'text/css' style.html <%= Rails.application.assets['shared/modal'].to_s %> $('head').append style Programmatically Use Assets #to_s - Render Asset #length - Bytes

Slide 68

Slide 68 text

Uses Of Assets _buildStyle: -> return unless @options.injectStyle style = $('') style.attr 'type', 'text/css' style.html <%= Rails.application.assets['shared/modal'].to_s %> $('head').append style Programmatically Use Assets #to_s - Render Asset #length - Bytes #mtime - Last Modified

Slide 69

Slide 69 text

Uses Of Assets _buildStyle: -> return unless @options.injectStyle style = $('') style.attr 'type', 'text/css' style.html <%= Rails.application.assets['shared/modal'].to_s %> $('head').append style Programmatically Use Assets #to_s - Render Asset #length - Bytes #mtime - Last Modified #pathname - Full Path

Slide 70

Slide 70 text

Other Asset Envs & Lazy Eval 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 In config/application.rb

Slide 71

Slide 71 text

Precompiling & Digests $ rake assets:precompile $ tree public/assets ... !"" application-3d94ca17a2aa6425c775e38a658f75b7.js !"" application-3d94ca17a2aa6425c775e38a658f75b7.js.gz !"" application-5a38464d5ec7e849e138184f810d4fc1.css !"" application-5a38464d5ec7e849e138184f810d4fc1.css.gz !"" application.css !"" application.css.gz !"" application.js !"" application.js.gz

Slide 72

Slide 72 text

The Future?

Slide 73

Slide 73 text

JavaScript Source Maps http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/ https://github.com/sstephenson/sprockets/pull/311

Slide 74

Slide 74 text

CommonJS Proposal https://github.com/sstephenson/sprockets/issues/298

Slide 75

Slide 75 text

Other Resrouces

Slide 76

Slide 76 text

Sass/Compass/LESS Tips & Tricks http://speakerdeck.com/u/beausmith/p/less-tips-tricks-best-practices

Slide 77

Slide 77 text

Thanks! Ken Collins metaskills.net