Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not reloading CSS correctly with config.assets.debug = false #169

Open
humphreybc opened this issue Sep 22, 2016 · 8 comments
Open

Not reloading CSS correctly with config.assets.debug = false #169

humphreybc opened this issue Sep 22, 2016 · 8 comments

Comments

@humphreybc
Copy link

In my development environment I've set config.assets.debug to false to speed up page load times when developing locally otherwise they can take a few seconds. However that seems to have broken guard-livereload reloading CSS. When I make changes, the page breaks and I get a 404:

Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:3000/assets/application-c4b62a8bfc31eeea5238d36f14e83a28dcd43c2a670cad8ba98a737ab6f3ccef.css?livereload=1474539326467

My app/assets/stylesheets folder is a pretty standard Rails structure with an application.css.scss file that imports all the other smaller CSS files in the same folder.

stylesheets
- application.css.scss
- basic.scss
- buttons.scss
... and so on

My Guardfile is standard. I have Ruby 2.3.1p112 and Rails 5.0.0.1. Is guard-livereload not compatible with this option? Thanks for the help.

@jibiel
Copy link
Member

jibiel commented Sep 22, 2016

We have guard-livereload and config.assets.debug = false at work and I've never had any problems with it. Livereloads just fine.

Maybe it's a Rails 5 thing cause we still on 4.2.

@larissa
Copy link

larissa commented Oct 27, 2016

I have the same issue with liveguard and Rails 5.0.0.1 with config.assets.debug set to false.

@humphreybc Were you able to fix it?

@bianjp
Copy link

bianjp commented Jan 11, 2017

Meet the same problem with Rails 5.0.1 and Sprocket 4.0.0.beta4 (or 3.7.1).

Solved it by adding config.assets.digest = false to config/environments/development.rb.

Not sure what exactly caused the problem. My guess is that Rails 5 won't respond to asset request with incorrect digest any more (livereload resend asset request with query string ?livereload=1474539326467 appended but doesn't change the digest ).

@unmultimedio
Copy link

Thanks a lot @bianjp it solved the problem to me too. You think it could be something with sprockets?

Could you please explain what exactly disabling digest does? Here is not very clear.

We have in Gemfile.lock

...
guard
guard-livereload (~> 2.5)
...
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
...

@bianjp
Copy link

bianjp commented Jan 18, 2017

Assets urls in Rails are like the following:

  • Rails 4.2: http://localhost:3000/assets/bootstrap/dist/css/bootstrap.self-ce4ff876691504f0f28b3c9bae0e691c640bbc9e2c4aa6dc2fe9fe0fe7e9bb1b.css?body=1,
  • Rails 5.0: http://localhost:3000/assets/application.debug-a0ec95c700718a9f98e10a97241e5983d38fdcc55a44d1c4c55c9749728d5123.css

Note that assets urls in Rails 4.2 contain query string '?body=1'.

Look at the following code in sprockets 3.7.1 (I marked the line number in comments):

# Line 47
options[:pipeline] = :self if body_only?(env)

asset = find_asset(path, options)

# 2.x/3.x compatibility hack. Just ignore fingerprints on ?body=1 requests.
# 3.x/4.x prefers strong validation of fingerprint to body contents, but
# 2.x just ignored it.
if asset && parse_asset_uri(asset.uri)[1][:pipeline] == "self"
  fingerprint = nil
end

# Line 70
elsif fingerprint && asset.etag != fingerprint
  status = :not_found

# Line 240
# Test if `?body=1` or `body=true` query param is set
def body_only?(env)
  env["QUERY_STRING"].to_s =~ /body=(1|t)/
end

So the following behaviors together lead to the failure of css live updating if assets digest is enabled:

  1. Livereload just adds a timestamp to the asset url's query string, and doesn't change the digest
  2. Assets url in Rails 5.0 don't contain '?body=1' query string
  3. Sprockets 4.0.0 beta removed the 2.x/3.x compatibility hack
  4. If digest in the url doesn't match the actual digest, Sprockets returns 404

Disabling assets digest bypasses the digest validation, so it works.

@potentialize
Copy link

I can confirm that @bianjp's analysis still holds on Rails version 6.0.2.1.
Adding config.assets.digest = false to config/environments/development.rb made the following error go away:

ActionController::RoutingError (No route matches [GET] "/assets/application.debug-823680184a29413ac2bd1b5608c0f7802f4e832b0a4d193588a28bef50ad32fb.css")

I guess this is a fine workaround for a development environment.
However, the core of this problem is that livereload does not know about the updated digest of assets. Maybe this should be solved in the rack-livereload gem?

Reference: https://guides.rubyonrails.org/asset_pipeline.html

@gregblass
Copy link

@potentialize Thank you! This worked for me with Rails 6!

@ralfebert
Copy link

ralfebert commented Oct 20, 2021

Also had to set this in development.rb to make it work in Rails 6:

config.assets.debug = true
config.assets.digest = false

This is not ideal, because without the digest assets like js are then sometimes not up-to-date and need an explicit browser refresh.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants