rework the asset pipeline to use environments

This commit is contained in:
Sven Fuchs 2012-10-06 15:28:11 +02:00
parent f6ac7b9c30
commit c6223341f4
15 changed files with 40298 additions and 3219 deletions

View File

@ -1,25 +1,18 @@
$: << 'lib' $: << 'lib'
require 'rake-pipeline-web-filters' require 'rake-pipeline-web-filters'
require 'rake-pipeline/travis' require 'travis/assets'
require 'compass' require 'compass'
ROOTS ||= [Pathname.new(File.expand_path('.'))] assets ||= Travis::Assets.new
assets.setup_compass
paths = %w(styles scripts images static vendor).inject({}) do |paths, type| assets.update_version
paths.merge(type.to_sym => ROOTS.map { |root| root.join("assets/#{type}").to_s })
end
Compass.configuration.images_path = paths[:images].first
Compass.configuration.add_import_path paths[:styles].first
Travis::Version.update
output 'public/scripts' output 'public/scripts'
input paths[:scripts] do input assets.scripts do
match '**/*.hbs' do match '**/*.hbs' do
travis_handlebars handlebars :precompile => assets.production?
concat 'app/templates.js' concat 'templates.js'
end end
match '**/*.coffee' do match '**/*.coffee' do
@ -27,38 +20,29 @@ input paths[:scripts] do
end end
match 'vendor/**/*.js' do match 'vendor/**/*.js' do
precedence = %w(jquery.min minispade handlebars ember).map { |name| "vendor/#{name}.js" } safe_concat assets.vendor_order, 'vendor.js'
safe_concat precedence, 'vendor.js' end
match %r(^(?!vendor).*\.js$) do
modules = proc { |input| input.path.gsub(%r((^app/|lib/|\.js$)), '') }
minispade(string: assets.development?, rewrite_requires: true, module_id_generator: modules)
end end
match '**/*.js' do match '**/*.js' do
copy { |path| ["dev/#{path}", "min/#{path}"] } concat ['vendor.js'], ['app.js', 'min/app.js']
end end
match %r(^dev/(?!vendor).*\.js$) do if assets.production?
modules = proc { |input| input.path.gsub(%r((^dev/|app/|lib/|\.js$)), '') } match 'min/app.js' do
minispade(string: true, rewrite_requires: true, module_id_generator: modules)
end
match 'dev/**/*.js' do
concat ['dev/vendor.js'], 'app.js'
end
match %r(^min/(?!vendor).*\.js$) do
modules = proc { |input| input.path.gsub(%r((^min/|app/|lib/|\.js$)), '') }
minispade(string: false, rewrite_requires: true, module_id_generator: modules)
end
match 'min/**/*.js' do
concat ['min/vendor.js'], 'min/app.js'
strip_debug strip_debug
uglify squeeze: true, max_line_length: 200 uglify squeeze: true
copy 'app.min.js' concat 'app.min.js'
end
end end
end end
output 'public/styles' output 'public/styles'
input paths[:styles] do input assets.styles do
match '**/*.{scss,sass}' do match '**/*.{scss,sass}' do
sass sass
concat [], 'app.css' concat [], 'app.css'
@ -66,7 +50,7 @@ input paths[:styles] do
end end
output 'public/images' output 'public/images'
input paths[:images] do input assets.images do
skip %r(^ui/) skip %r(^ui/)
match '**/*' do match '**/*' do
copy copy
@ -74,7 +58,7 @@ input paths[:images] do
end end
output 'public' output 'public'
input paths[:static] do input assets.static do
match '**/*' do match '**/*' do
copy copy
end end

View File

@ -21,7 +21,7 @@ group :development do
gem 'newrelic_rpm', '~> 3.3.0' gem 'newrelic_rpm', '~> 3.3.0'
gem 'hubble', github: 'roidrage/hubble' gem 'hubble', github: 'roidrage/hubble'
gem 'rake-pipeline', github: 'livingsocial/rake-pipeline' gem 'rake-pipeline', github: 'livingsocial/rake-pipeline', ref: '3465e0e3e1'
gem 'rake-pipeline-web-filters', github: 'wycats/rake-pipeline-web-filters' gem 'rake-pipeline-web-filters', github: 'wycats/rake-pipeline-web-filters'
gem 'coffee-script' gem 'coffee-script'

View File

@ -1,9 +1,9 @@
GIT GIT
remote: git://github.com/livingsocial/rake-pipeline.git remote: git://github.com/livingsocial/rake-pipeline.git
revision: 3914452278165b7eb3a79071d3b63b46fee59a2f revision: 3465e0e3e134bf52ddf5d138e8c8262412080095
ref: 3465e0e3e1
specs: specs:
rake-pipeline (0.6.0) rake-pipeline (0.6.0)
json
rake (~> 0.9.0) rake (~> 0.9.0)
thor thor

View File

@ -10,7 +10,7 @@ This is a static html/js app so you shouldn't need to install anything.
Running locally with a local API server: Running locally with a local API server:
bundle exec rackup RUN_API=1 bundle exec rackup -p 3000
Running against existing API endpoint: Running against existing API endpoint:
@ -24,6 +24,7 @@ Run locally, one on `ci.dev` and one on `api.dev`:
### Compiling assets manually ### Compiling assets manually
bundle exec rakep bundle exec rakep
ENV=production bundle exec rakep
### Compiling assets on change ### Compiling assets on change

View File

@ -26,7 +26,10 @@ module Guard
private private
def run def run
started = Time.now
print 'Compiling ... '
system 'bundle exec rakep' system 'bundle exec rakep'
puts "done (#{(Time.now - started).round(2)}s)."
end end
end end
end end

View File

@ -1,9 +0,0 @@
require 'rake-pipeline'
module Rake::Pipeline::Travis
autoload :Filters, 'rake-pipeline/travis/filters'
autoload :Helpers, 'rake-pipeline/travis/helpers'
autoload :Version, 'rake-pipeline/travis/version'
end
Rake::Pipeline::DSL::PipelineDSL.send(:include, Rake::Pipeline::Travis::Helpers)

View File

@ -1,54 +0,0 @@
require 'pathname'
require 'digest/md5'
module Rake::Pipeline::Travis
class Version
FILE_NAME = 'public/version'
SOURCES = %w(AssetFile Gemfile.lock assets)
def self.update
new.update
end
attr_reader :root
def initialize(root = nil)
@root = Pathname.new(root || File.expand_path('.'))
end
def read
file.read
end
def update
@hash = nil
write(hash)
hash
end
protected
def file
root.join(FILE_NAME)
end
def write(version)
file.open('w+') { |f| f.write(version) }
end
def hash
@hash ||= digest.to_s[0..7]
end
def digest
Digest::MD5.new << `ls -lAR #{sources.join(' ')} | awk '{print $5, $6, $7, $9}'`
end
def sources
SOURCES.map do |source|
source = root.join(source)
source.to_s if source.exist?
end.compact
end
end
end

52
lib/travis/assets.rb Normal file
View File

@ -0,0 +1,52 @@
require 'rake-pipeline'
module Travis
class Assets
autoload :Filters, 'travis/assets/filters'
autoload :Helpers, 'travis/assets/helpers'
autoload :Version, 'travis/assets/version'
TYPES = [:styles, :scripts, :images, :static, :vendor]
VENDOR_ORDER = %w(jquery.min minispade handlebars ember)
attr_reader :roots, :env
def initialize(roots = '.')
@roots = Array(roots).map { |root| Pathname.new(File.expand_path(root)) }
@env = ENV['ENV']
end
def production?
env == 'production'
end
def development?
!production?
end
def vendor_order
VENDOR_ORDER.map { |name| "vendor/#{name}.js" }
end
def setup_compass
Compass.configuration.images_path = images.first
styles.each do |path|
Compass.configuration.add_import_path(path)
end
end
def update_version
Travis::Assets::Version.new.update
end
TYPES.each { |type| define_method(type) { paths[type] } }
def paths
@paths ||= TYPES.inject({}) do |paths, type|
paths.merge(type.to_sym => roots.map { |root| root.join("assets/#{type}").to_s })
end
end
end
end
Rake::Pipeline::DSL::PipelineDSL.send(:include, Travis::Assets::Helpers)

View File

@ -1,19 +1,18 @@
require 'rake-pipeline' require 'rake-pipeline'
require 'execjs' require 'execjs'
require 'uglifier' require 'uglifier'
require 'pathname' require 'pathname'
class Rake::Pipeline
module Travis module Travis
class Assets
module Filters module Filters
class Drop < Matcher class Drop < Rake::Pipeline::Matcher
def output_files def output_files
input_files.reject { |f| f.path =~ @pattern } input_files.reject { |f| f.path =~ @pattern }
end end
end end
class Handlebars < Filter class Handlebars < Rake::Pipeline::Filter
class << self class << self
def source def source
[ [
@ -30,22 +29,35 @@ class Rake::Pipeline
def context def context
@@context ||= ExecJS.compile(source) @@context ||= ExecJS.compile(source)
end end
def compile(source)
context.call('compileHandlebarsTemplate', source + "\n")
end end
attr_reader :options
def initialize(*args, &block)
@options = args.last.is_a?(Hash) ? args.pop : {}
super
end end
def generate_output(inputs, output) def generate_output(inputs, output)
inputs.each do |input| inputs.each do |input|
source = self.class.compile(input.read) source = input.read
source = options[:precompile] ? compile(source) : escape(source)
source = wrap(name(input.path), source) source = wrap(name(input.path), source)
output.write source output.write source
end end
end end
def compile(source)
self.class.context.call('compileHandlebarsTemplate', source + "\n")
end
def escape(source)
source.to_json
end
def wrap(name, source) def wrap(name, source)
"\nEmber.TEMPLATES['#{name}'] = Ember.Handlebars.template(#{source});\n" method = options[:precompile] ? 'template' : 'compile'
"\nEmber.TEMPLATES['#{name}'] = Ember.Handlebars.#{method}(#{source});\n"
end end
def name(path) def name(path)
@ -53,7 +65,7 @@ class Rake::Pipeline
end end
end end
class SafeConcat < ConcatFilter class SafeConcat < Rake::Pipeline::ConcatFilter
def generate_output(inputs, output) def generate_output(inputs, output)
inputs.each do |input| inputs.each do |input|
output.write File.read(input.fullpath) + ";" output.write File.read(input.fullpath) + ";"
@ -76,7 +88,7 @@ class Rake::Pipeline
end end
end end
class StripDebug < Filter class StripDebug < Rake::Pipeline::Filter
def generate_output(inputs, output) def generate_output(inputs, output)
inputs.each do |input| inputs.each do |input|
source = File.read(input.fullpath) source = File.read(input.fullpath)

View File

@ -1,9 +1,9 @@
require 'rake-pipeline/dsl' require 'rake-pipeline/dsl'
class Rake::Pipeline
module Travis module Travis
class Assets
module Helpers module Helpers
def travis_handlebars(*args, &block) def handlebars(*args, &block)
filter(Filters::Handlebars, *args, &block) filter(Filters::Handlebars, *args, &block)
end end

View File

@ -0,0 +1,56 @@
require 'pathname'
require 'digest/md5'
module Travis
class Assets
class Version
FILE_NAME = 'public/version'
SOURCES = %w(AssetFile Gemfile.lock assets)
def self.update
new.update
end
attr_reader :root
def initialize(root = nil)
@root = Pathname.new(root || File.expand_path('.'))
end
def read
file.read
end
def update
@hash = nil
write(hash)
hash
end
protected
def file
root.join(FILE_NAME)
end
def write(version)
file.open('w+') { |f| f.write(version) }
end
def hash
@hash ||= digest.to_s[0..7]
end
def digest
Digest::MD5.new << `ls -lAR #{sources.join(' ')} | awk '{print $5, $6, $7, $9}'`
end
def sources
SOURCES.map do |source|
source = root.join(source)
source.to_s if source.exist?
end.compact
end
end
end
end

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

34866
public/scripts/min/app.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
096c4ea9 5f08468e