Clear the cache from the Rails asset pipeline
Asked Answered
A

5

66

I'm starting a new project in Rails, and it looks like the application.js manifest file is doing something funny with the javascripts that I reference - does it cache those files as part of the asset pipeline?

Here's what happened. I added a javascript file named jquery.autoresize.js to the vendor/assets/javascripts folder, and then referenced the file in the application.js manifest like this:

//= require jquery.autoresize.js 

Then I started up the rails server. But after navigating around in my app, I realized that I had accidentally added the wrong version of the jquery.autoresize.js file. So, I deleted that file and then added the correct version to the vendor/assets/javascripts folder. But, to my horror, when I reloaded the page, it is still loading the old javascript file.

I tried emptying my browser cache, then exiting and restarting the Rails server, but to no avail. I hacked a solution together by simply renaming my javascript file and referencing the new name, which worked fine. But there has got to be a better solution to this.

Does the new asset pipeline cache the files you reference somehow? If so, how can I clear that cache? Thanks for any help!

Axiom answered 4/4, 2012 at 2:58 Comment(1)
I cannot believe I wasted over an hour on this. What finally fixed it for me was resetting the browser's cache! Chrome > Clear Browsing Data > Cached Images & FilesFunderburk
R
69

I'm assuming we're talking about the production environment.

When you change any of your javascripts or stylesheets in the production environment, you need to run rake assets:precompile; this task compiles and compresses the various .js and .css files and creates the application.js and application.css files that is loaded by your views.

It's possible that if you replaced jquery.autoresize.js with a version with an older timestamp, the precompile step might skip it, thinking the compiled version is up-to-date. You can avoid that by running rake assets:clean first, forcing it to rebuild everything in the public/assets directory from scratch.

Russom answered 5/9, 2012 at 23:22 Comment(4)
Ahh, very interesting, thanks for your thoughts. I was actually doing this on my local development environment, and I never ran rake assets:precompile. So, perhaps that makes it behave differently? Do you think that the development environment would cause it to behave in the way that I described originally?Axiom
In the development environment, the hashed filenames are not used, so everything is based on file modification dates. (Do view-source in a browser to see the script links in the HTML header.) My guess is that in the dev environment, the replacement file had an older modification date, and so the browser was just using its cached version. Your edit updated the file's mod time, and that's why the browser finally fetched the new version.Russom
Awesome. Thanks for helping me figure this out. I will modify the content of the question and stuff to better explain and give you credit for helping out.Axiom
RAILS_ENV=development bundle exec rake assets:clean, RAILS_ENV=development bundle exec rake assets:precompile, and RAILS_ENV=development bundle exec rails server is what finally did it for me.Lovelady
M
72

Also try rake assets:clobber. This will totally reset everything and delete all compiled assets. In addition, I often need to set the environment before pushing to production by going: RAILS_ENV=production rake assets:precompile.

Mendacious answered 20/7, 2015 at 13:11 Comment(3)
+1! This solution worked for me. I'm developing a custom asset-pipeline processor and this makes Sprockets enter to the processor again. ThxAmbo
probably the best answerLibbielibbna
It also works against importmap-rails when there is old js files in public/assets/javascript raising in console some not found responses.Ankylosaur
R
69

I'm assuming we're talking about the production environment.

When you change any of your javascripts or stylesheets in the production environment, you need to run rake assets:precompile; this task compiles and compresses the various .js and .css files and creates the application.js and application.css files that is loaded by your views.

It's possible that if you replaced jquery.autoresize.js with a version with an older timestamp, the precompile step might skip it, thinking the compiled version is up-to-date. You can avoid that by running rake assets:clean first, forcing it to rebuild everything in the public/assets directory from scratch.

Russom answered 5/9, 2012 at 23:22 Comment(4)
Ahh, very interesting, thanks for your thoughts. I was actually doing this on my local development environment, and I never ran rake assets:precompile. So, perhaps that makes it behave differently? Do you think that the development environment would cause it to behave in the way that I described originally?Axiom
In the development environment, the hashed filenames are not used, so everything is based on file modification dates. (Do view-source in a browser to see the script links in the HTML header.) My guess is that in the dev environment, the replacement file had an older modification date, and so the browser was just using its cached version. Your edit updated the file's mod time, and that's why the browser finally fetched the new version.Russom
Awesome. Thanks for helping me figure this out. I will modify the content of the question and stuff to better explain and give you credit for helping out.Axiom
RAILS_ENV=development bundle exec rake assets:clean, RAILS_ENV=development bundle exec rake assets:precompile, and RAILS_ENV=development bundle exec rails server is what finally did it for me.Lovelady
A
28

Rails automatically clears the cache for an individual file every time that the contents are edited. To clear the cache for a single file, simply open the file, edit a line of code, and re-save it. Rails will clear the cache for that file, and the browser will load the new file the next time the page is loaded.

The reason jquery.autoresize.js was using the old cached version of the file was because the old version was deleted and then the new version was copied and pasted with the same name into the same folder. Because the file itself was never edited, Rails continued to use the old file that was cached.

This is because the asset pipeline uses fingerprinting for the cache.

Fingerprinting is a technique that makes the name of a file dependent on the contents of the file. When the file contents change, the filename is also changed. For content that is static or infrequently changed, this provides an easy way to tell whether two versions of a file are identical, even across different servers or deployment dates.

When a filename is unique and based on its content, HTTP headers can be set to encourage caches everywhere (whether at CDNs, at ISPs, in networking equipment, or in web browsers) to keep their own copy of the content. When the content is updated, the fingerprint will change. This will cause the remote clients to request a new copy of the content. This is generally known as cache busting.

The technique that Rails uses for fingerprinting is to insert a hash of the content into the name, usually at the end. For example a CSS file global.css could be renamed with an MD5 digest of its contents:

global-908e25f4bf641868d8683022a5b62f54.css

So, if you delete a file you're referencing in the manifest, and then copy in a new file with the same name, the cache busting never occurs. When you edit the file, the fingerprinting kicks in, and a new hash is generated for the file name. This busts the cache for that file.

For the full story, see What is Fingerprinting and Why Should I Care?.

Axiom answered 4/4, 2012 at 4:23 Comment(9)
I don't think this is correct. The fingerprint is based on the contents of the file. If you delete a file and replace it with a different one with the same name, you'll get a different fingerprint, and a different file name.Russom
Thanks for chiming in. Have you tried this in one of your own projects recently? Because I can definitely confirm that when I created this question, the only way I could get the new file to be loaded by my browser was to edit a single line of code and resave it. If it is working for you by simply deleting the file and replacing it with a new one with the same name, I would love to hear about it.Axiom
I had a different asset pipeline issue, which is how I came across this question. You say "if you delete a file you're referencing in the manifest, and then copy in a new file with the same name, the cache busting never occurs"; that would only be true if the new/old file had identical contents, in which case who cares which version you have? If you're talking about production mode, you need to run rake assets:precompile to put the files in the public/assets directory; that should be the solution unless you've changed the default config.Russom
Aaron is right, I had the same problem (in dev mode) and tried everything - rake assets:clean, then rake assets:precompile, as well as copying the new file over again and restarting the server. Nothing worked until I opened the new file, added a few dummy words at the end, then deleted them and saved the file. Rails is becoming too complex for it's own good - you know that's the case when simple things require complex steps to get done.Showboat
Unfortunately not even @user906230's solution worked. Rails just continues to serve the old file, I've done everything besides debugging asset pipeline directly. If anybody has solved this please write a comment.Herren
@Herren you need to clear you assets cache try running all of the following then recompiiging: Run the following commands: ``` rake assets:clean rake tmp:clear rake tmp:cache:clear rake cache:clear ```Superdreadnought
rather than editing the file, you can run touch on the file to update the timestamp on it. You can see if this is the issue by running ls -l and checking the modification date.Coddle
I ran into a similar problem and none of the above solutions helped. We have application.css include a single file (with sprockets' *= require syntax) which then includes further files using compass's @import. Changing files below the @import used to fix things but then after a precompile in dev once it started returning the cached precompiled version. I fixed this by modifying application.css and rerequesting. That busted the cache and now it reloads appropriately.Hardback
Incredible that 4 years later this is still a problem. rake tmp:clear did nothing, I really had to add an empty line to the file to make it work.Reneerenegade
I
23

rake tmp:clear did the trick for me, I'm using less-rails.

Indistinctive answered 10/8, 2016 at 17:21 Comment(2)
I have to do this as well to get browserify-rails to update, otherwise it will find and use old files that have since been deleted. rails assets:clean does not work for this.Beals
That is the only way for me to have the files properly rebuilt when they depend on changing environnement variables. Clean and Clobber seem not to be enough in such a case.Dejecta
R
6

I use config.assets.version = '1.01019' in my application.rb to bust the entire cache. When I want to push a complete new version, I increment the version and that does the trick. This takes care of those edge cases where Rails does not recompile as asset for whatever reason.

Rebuild answered 3/3, 2015 at 21:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.