From 140cd0e23285519fa03727dde9c47365824e9af2 Mon Sep 17 00:00:00 2001 From: Patrick Hogan Date: Thu, 1 Apr 2010 11:33:24 -0500 Subject: [PATCH] Added wildcards. Improved caching considerably for Rack::Cache and Rack::ConditionalGet by including etags. Performance improvements. --- lib/sinatra/bundles.rb | 18 ++++++++---- lib/sinatra/bundles/bundle.rb | 37 ++++++++++++++++++++++-- lib/sinatra/bundles/helpers.rb | 4 +-- lib/sinatra/bundles/stylesheet_bundle.rb | 6 ++-- 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/lib/sinatra/bundles.rb b/lib/sinatra/bundles.rb index ffe30cc..3adb373 100644 --- a/lib/sinatra/bundles.rb +++ b/lib/sinatra/bundles.rb @@ -11,7 +11,7 @@ module Bundles # @param [Symbol,String] key The bundle name # @param [Array(String)] files The list of filenames, without extension, # assumed to be in the public directory, under 'javascripts' - def javascript_bundle(key, files) + def javascript_bundle(key, files = nil) javascript_bundles[key] = JavascriptBundle.new(self, files) end @@ -20,7 +20,7 @@ def javascript_bundle(key, files) # @param [Symbol,String] key The bundle name # @param [Array(String)] files The list of filenames, without extension, # assumed to be in the public directory, under 'stylesheets' - def stylesheet_bundle(key, files) + def stylesheet_bundle(key, files = nil) stylesheet_bundles[key] = StylesheetBundle.new(self, files) end @@ -46,15 +46,21 @@ def self.registered(app) app.get('/stylesheets/bundles/:bundle.css') do |bundle| content_type('text/css') headers['Vary'] = 'Accept-Encoding' - expires(options.bundle_cache_time, :public, :must_revalidate) if options.cache_bundles - options.stylesheet_bundles[bundle.intern] + if options.cache_bundles + expires(options.bundle_cache_time, :public, :must_revalidate) + etag options.stylesheet_bundles[bundle.intern].etag + end + options.stylesheet_bundles[bundle.intern].content end app.get('/javascripts/bundles/:bundle.js') do |bundle| content_type('text/javascript; charset=utf-8') headers['Vary'] = 'Accept-Encoding' - expires(options.bundle_cache_time, :public, :must_revalidate) if options.cache_bundles - options.javascript_bundles[bundle.intern] + if options.cache_bundles + expires(options.bundle_cache_time, :public, :must_revalidate) + etag options.javascript_bundles[bundle.intern].etag + end + options.javascript_bundles[bundle.intern].content end end end diff --git a/lib/sinatra/bundles/bundle.rb b/lib/sinatra/bundles/bundle.rb index d77035d..7c6bedc 100644 --- a/lib/sinatra/bundles/bundle.rb +++ b/lib/sinatra/bundles/bundle.rb @@ -4,9 +4,29 @@ module Bundles # The developer user sinatra-bundles should # never have to deal with this directly class Bundle - def initialize(app, files) + include Enumerable + + def initialize(app, files = nil) @app = app - @files = files + @files = Array.new + files ||= ["**"] + files.each do |f| + full_path = path(f) + if File.file? full_path + @files << f + else + dir = File.dirname(full_path) + ext = File.extname(full_path) + pattern = File.join(dir, f, "**", "*#{ext}") + Dir.glob(pattern) do |file| + file.chomp!(ext).slice!(0..dir.length) + @files << file + end + end + end + @files.uniq! + etag + # puts @files.inspect end # Since we pass Bundles back as the body, @@ -21,8 +41,19 @@ def each end end - private + # Returns the bundled content. + # Cached in a local variable to prevent rebundling on future requests. + def content + @content ||= self.to_a.join('') + end + # Returns an etag for the bundled content. + # Cached in a local variable to prevent recomputing on future requests. + def etag + @etag ||= Digest::MD5.hexdigest(content) + end + + private # The timestamp of the bundle, which is the newest file in the bundle. # # @return [Integer] The timestamp of the bundle diff --git a/lib/sinatra/bundles/helpers.rb b/lib/sinatra/bundles/helpers.rb index 7fcd344..16875bb 100644 --- a/lib/sinatra/bundles/helpers.rb +++ b/lib/sinatra/bundles/helpers.rb @@ -14,8 +14,8 @@ def javascript_bundle_include_tag(bundle) # # @param [Symbol,String] bundle The bundle name # @return [String] HTML link tag - def stylesheet_bundle_link_tag(bundle) - options.stylesheet_bundles[bundle].to_html(bundle) + def stylesheet_bundle_link_tag(bundle, media = nil) + options.stylesheet_bundles[bundle].to_html(bundle, media) end end end diff --git a/lib/sinatra/bundles/stylesheet_bundle.rb b/lib/sinatra/bundles/stylesheet_bundle.rb index 62b805d..c965eb7 100644 --- a/lib/sinatra/bundles/stylesheet_bundle.rb +++ b/lib/sinatra/bundles/stylesheet_bundle.rb @@ -9,8 +9,10 @@ class StylesheetBundle < Bundle # # @param [String] name The name of a bundle # @return [String] The HTML that can be inserted into the doc - def to_html(name) - "" + def to_html(name, media = nil) + media ||= :all + media = media.join(", ") if media.is_a? Array + "" end protected