Gary Weaver
2012-Dec-18 20:57 UTC
cache-busting non-digest assets in sprockets in development a good idea? should headers in sprockets be configurable?
Just monkey patched Sprockets in our Rails 3.2.9 app to override the Cache-Control header for html assets that we need to tweak more often in development, but that we don''t want to use digests/fingerprinting with: # Sprockets 2.x patch if Rails.env.development? module Sprockets module Server private alias_method :sprockets_headers, :headers def headers(env, asset, length) sprockets_headers(env, asset, length).tap do |headers| # cache-bust .html assets because in our case they are frequently AngularJS templates we need to tweak if !path_fingerprint(env["PATH_INFO"]) && asset.pathname.basename.to_s[''.html''] headers["Cache-Control"] = "max-age=0, private, must-revalidate" end end end end end end Would the ability to configure "Cache-Control" and other headers (or add headers) in responses for assets in Sprockets be helpful to have available in Rails, or is it just assumed that if you need that level of control, you''ll fix it elsewhere with nginx, apache, etc.? Why I''m asking is that Heroku shows here how to change expiry of actions: https://devcenter.heroku.com/articles/http-caching-ruby-rails but, I couldn''t find anywhere that talked about how to expire assets other than using digests/fingerprinting, until I came across server.rb in sprockets and realized that it didn''t look like it was possible without monkey patching or using another gem that would override the headers. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-core/-/fgvsaflGLIcJ. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Gary Weaver
2012-Dec-19 16:13 UTC
Re: cache-busting non-digest assets in sprockets in development a good idea? should headers in sprockets be configurable?
I also tried using digest in development and learned something: you can change an asset by moving one section of the file to another section and even though the file is thumbprinted/digested, sometimes the browser won''t reload it. Basically, I changed config/environments/development.rb to use: config.assets.debug = false config.assets.digest = true and much of the time if I move one section of the file to another part of the same file (and I tried in a few different ways), the browser (FF 17 in OS X) won''t reload the asset because it is still cached, even when I am forcing Sprockets to cache-bust via this patch in config/initializers/.../name_of_my_patch.rb # Sprockets 2.x patch to cache-bust non-fingerprinted angular template html in development if Rails.env.development? module Sprockets module Server private # want to attempt to be compatible as much as possible so we''ll call their headers method ''sprockets_headers'' and then # override just the headers we want. this may or may not work in future versions as this is a private method. alias_method :sprockets_headers, :headers def headers(env, asset, length) sprockets_headers(env, asset, length).tap do |headers| # both digested/thumbprinted and non-digested files seem to not refresh cache (at least with FF 17) # so, use cache-busters for .../app/assets/**/* if asset.pathname.to_s[''/app/assets/''] puts "cache-busting #{asset.pathname.to_s} etag_header=#{headers["ETag"]} path_fingerprint(env[\"PATH_INFO\"])=#{path_fingerprint(env["PATH_INFO"])}" headers["Cache-Control"] = "max-age=0, private, must-revalidate" end end end end end end However, with that patch, if I comment out the following: #config.assets.debug = false #config.assets.digest = true It seems to work as intended. On Tuesday, December 18, 2012 3:57:46 PM UTC-5, Gary Weaver wrote:> > Just monkey patched Sprockets in our Rails 3.2.9 app to override the > Cache-Control header for html assets that we need to tweak more often in > development, but that we don''t want to use digests/fingerprinting with: > > # Sprockets 2.x patch > if Rails.env.development? > module Sprockets > module Server > > private > alias_method :sprockets_headers, :headers > > def headers(env, asset, length) > sprockets_headers(env, asset, length).tap do |headers| > # cache-bust .html assets because in our case they are > frequently AngularJS templates we need to tweak > if !path_fingerprint(env["PATH_INFO"]) && > asset.pathname.basename.to_s[''.html''] > headers["Cache-Control"] = "max-age=0, private, > must-revalidate" > end > end > end > end > end > end > > Would the ability to configure "Cache-Control" and other headers (or add > headers) in responses for assets in Sprockets be helpful to have available > in Rails, or is it just assumed that if you need that level of control, > you''ll fix it elsewhere with nginx, apache, etc.? > > Why I''m asking is that Heroku shows here how to change expiry of actions: > https://devcenter.heroku.com/articles/http-caching-ruby-rails > > but, I couldn''t find anywhere that talked about how to expire assets other > than using digests/fingerprinting, until I came across server.rb in > sprockets and realized that it didn''t look like it was possible without > monkey patching or using another gem that would override the headers. > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-core/-/LjvlTx7rRFQJ. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Gary Weaver
2012-Dec-19 16:59 UTC
Re: cache-busting non-digest assets in sprockets in development a good idea? should headers in sprockets be configurable?
May not be a bug, really, but opened here for discussion, because it would seem that a file not changing its digest when it changes is a problem: https://github.com/sstephenson/sprockets/issues/399 On Wednesday, December 19, 2012 11:13:11 AM UTC-5, Gary Weaver wrote:> > I also tried using digest in development and learned something: you can > change an asset by moving one section of the file to another section and > even though the file is thumbprinted/digested, sometimes the browser won''t > reload it. > > Basically, I changed config/environments/development.rb to use: > > config.assets.debug = false > config.assets.digest = true > > and much of the time if I move one section of the file to another part of > the same file (and I tried in a few different ways), the browser (FF 17 in > OS X) won''t reload the asset because it is still cached, even when I am > forcing Sprockets to cache-bust via this patch in > config/initializers/.../name_of_my_patch.rb > > # Sprockets 2.x patch to cache-bust non-fingerprinted angular template > html in development > if Rails.env.development? > module Sprockets > module Server > > private > # want to attempt to be compatible as much as possible so we''ll call > their headers method ''sprockets_headers'' and then > # override just the headers we want. this may or may not work in > future versions as this is a private method. > alias_method :sprockets_headers, :headers > > def headers(env, asset, length) > sprockets_headers(env, asset, length).tap do |headers| > # both digested/thumbprinted and non-digested files seem to not > refresh cache (at least with FF 17) > # so, use cache-busters for .../app/assets/**/* > if asset.pathname.to_s[''/app/assets/''] > puts "cache-busting #{asset.pathname.to_s} > etag_header=#{headers["ETag"]} > path_fingerprint(env[\"PATH_INFO\"])=#{path_fingerprint(env["PATH_INFO"])}" > headers["Cache-Control"] = "max-age=0, private, > must-revalidate" > end > end > end > end > end > end > > However, with that patch, if I comment out the following: > > #config.assets.debug = false > #config.assets.digest = true > > It seems to work as intended. > > On Tuesday, December 18, 2012 3:57:46 PM UTC-5, Gary Weaver wrote: >> >> Just monkey patched Sprockets in our Rails 3.2.9 app to override the >> Cache-Control header for html assets that we need to tweak more often in >> development, but that we don''t want to use digests/fingerprinting with: >> >> # Sprockets 2.x patch >> if Rails.env.development? >> module Sprockets >> module Server >> >> private >> alias_method :sprockets_headers, :headers >> >> def headers(env, asset, length) >> sprockets_headers(env, asset, length).tap do |headers| >> # cache-bust .html assets because in our case they are >> frequently AngularJS templates we need to tweak >> if !path_fingerprint(env["PATH_INFO"]) && >> asset.pathname.basename.to_s[''.html''] >> headers["Cache-Control"] = "max-age=0, private, >> must-revalidate" >> end >> end >> end >> end >> end >> end >> >> Would the ability to configure "Cache-Control" and other headers (or add >> headers) in responses for assets in Sprockets be helpful to have available >> in Rails, or is it just assumed that if you need that level of control, >> you''ll fix it elsewhere with nginx, apache, etc.? >> >> Why I''m asking is that Heroku shows here how to change expiry of actions: >> https://devcenter.heroku.com/articles/http-caching-ruby-rails >> >> but, I couldn''t find anywhere that talked about how to expire assets >> other than using digests/fingerprinting, until I came across server.rb in >> sprockets and realized that it didn''t look like it was possible without >> monkey patching or using another gem that would override the headers. >> >>-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-core/-/HcNRNnZoz8gJ. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.