Created
March 9, 2010 14:18
-
-
Save ilpoldo/326616 to your computer and use it in GitHub Desktop.
metal-based asset packagers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'jsmin' | |
| require 'fileutils' | |
| require 'benchmark' | |
| module JavascriptMinifier | |
| class NotFound < StandardError; end | |
| class Responder | |
| @asset_folder = "#{Rails.root}/public/javascripts" | |
| @cache_folder = "#{Rails.root}/tmp/asset_cache" | |
| @cached = [] | |
| def self.asset_folder=(path) | |
| @asset_folder = path | |
| end | |
| def self.cache_folder=(path) | |
| @cache_folder = path | |
| end | |
| def self.call(env) | |
| bundle = Array(env["PATH_INFO"].match(/^\/javascripts\/(.*).js/))[1] | |
| case Rails.env | |
| when 'production' | |
| #TODO: deal with etag headers/cachebusters | |
| if @cached.include? bundle | |
| @cache_server.call(env) | |
| else | |
| prepare bundle | |
| @cache_server.call(env) | |
| end | |
| else | |
| serve files_for(bundle) | |
| end | |
| rescue NotFound | |
| [404, {"Content-Type" => "text/html"}, ["Not Found"]] | |
| end | |
| # Loads asset files inside the <bundle_name> folder in order: | |
| # 1.javascripts contained in <bundle_name>/base | |
| # 2.javascripts contained in <bundle_name>/pugins | |
| # 3.javascripts contained in the <bundle_name> folder | |
| def self.files_for(bundle) | |
| raise NotFound unless File.exists? File.join(@asset_folder, bundle) | |
| assets = [] | |
| Dir.chdir File.join(@asset_folder, bundle) do | |
| assets += Dir.glob('base/*.js') | |
| assets += Dir.glob('plugins/*.js') | |
| assets += Dir.glob('*.js') | |
| assets.map! {|p| File.expand_path p} | |
| end | |
| assets | |
| end | |
| # Reads each asset file in order and sends back the content | |
| def self.serve(assets) | |
| content = "" | |
| assets.each do |f| | |
| content << File.read(f) | |
| end | |
| [200, {"Content-Type" => "text/javascript", "Content-Length" => "#{content.bytesize}"}, [content]] | |
| end | |
| # Compresses the javascript and instantiates the rack server to serve the cached copy | |
| def self.prepare(bundle) | |
| cache_file = File.join(@cache_folder, 'javascripts', "#{bundle}.js") | |
| @cache_server ||= cache_server | |
| script = files_for(bundle).inject('') do |s, f| | |
| s << File.read(f) | |
| end | |
| File.open(cache_file, "w") { |f| f.puts JSMin.minify(script) } | |
| @cached << bundle | |
| end | |
| def self.cache_server | |
| FileUtils.mkdir_p File.join(@cache_folder, 'javascripts') | |
| rack_file = Rack::File.new(@cache_folder) | |
| lambda do |env| | |
| code, header, body = rack_file.call(env) | |
| [code, header.merge('Content-Type' => 'text/javascript'), body] | |
| end | |
| end | |
| end | |
| def self.call(env) | |
| response = nil | |
| js_runtime = Benchmark.ms {response = Responder.call(env)} | |
| Rails.logger.debug("Completed #{response.first} in %.1fms" % js_runtime) | |
| response | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Allow the metal piece to run in isolation | |
| require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails) | |
| require 'fileutils' | |
| Sass::Plugin.options[:check_for_updates] = false | |
| module SassCompiler | |
| class Responder | |
| class NotFound < StandardError; end | |
| class CompileError < StandardError; end | |
| @asset_folder = "#{Rails.root}/public/stylesheets" | |
| @cache_folder = "#{Rails.root}/tmp/asset_cache" | |
| @cached = [] | |
| def self.asset_folder=(path) | |
| @asset_folder = path | |
| end | |
| def self.cache_folder=(path) | |
| @cache_folder = path | |
| end | |
| def self.call(env) | |
| asset = Array(env["PATH_INFO"].match(/^\/stylesheets\/(.*).css/))[1] | |
| if Rails.env != 'development' and @cached.include? asset | |
| @cache_server.call(env) | |
| else | |
| sass_compile asset | |
| @cache_server.call(env) | |
| end | |
| rescue NotFound | |
| [404, {"Content-Type" => "text/html"}, ["Not Found"]] | |
| rescue CompileError => e | |
| [500, {"Content-Type" => "text/plain"}, [e.inspect]] | |
| end | |
| # Renders the sass files in the cache and instances an app to serve them | |
| def self.sass_compile(asset_name) | |
| asset = File.join(@asset_folder, "#{asset_name}.scss") | |
| raise NotFound unless File.exists? asset | |
| @cache_server ||= cache_server | |
| css = File.join(@cache_folder, 'stylesheets', "#{asset_name}.css") | |
| File.delete(css) if File.exists?(css) | |
| begin | |
| render_style = Rails.env == 'development' ? :nested : :compressed | |
| sass = Sass::Files.tree_for asset, :cache => true, | |
| :cache_location => File.join(@cache_folder, '.sass_cache'), | |
| :template_location => @asset_folder, | |
| :load_paths => compass_paths, | |
| :css_filename => css, | |
| :filename => asset, | |
| :style => render_style | |
| File.open(css, 'w') {|f| f << sass.render} | |
| # rescue Exception => e | |
| # raise CompileError(e) | |
| end | |
| @cached << asset_name | |
| end | |
| # Ensures a cache folder exists and instantiates the app to serve it. | |
| def self.cache_server | |
| FileUtils.makedirs File.join(@cache_folder, 'stylesheets') | |
| Rack::File.new(@cache_folder) | |
| end | |
| def self.compass_paths | |
| Compass::Frameworks::ALL.map {|framework| framework.stylesheets_directory if File.exists?(framework.stylesheets_directory)} | |
| rescue NameError | |
| [] | |
| end | |
| end | |
| def self.call(env) | |
| response = nil | |
| sass_runtime = Benchmark.ms {response = Responder.call(env)} | |
| Rails.logger.debug("Completed #{response.first} in %.1fms" % sass_runtime) | |
| response | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment