4

When navigating my site, my browser is loading the JS files from cache, but not the CSS files. This happens both running a local server and on the live site (to me and apparently to other users, which is apparent since the logs show mostly .css files getting loaded).

I've tried the other solutions (example): I am clicking around on hyperlinks (not refreshing) and my Chrome Devtools do not have "Disable Cache" checked.

Here is the initial request (using CTRL+F5 for a hard refresh):

enter image description here

Then navigating back to that page creates another request:

enter image description here

(Note: there is no Cache-Control sent in the second request, proving that I indeed did not refresh)

As expected, the server responds with a 304 Not-Modified for the .css file, but I don't understand why it's making a trip to the server at all (notice below the .js file is retrieved without a server request).

enter image description here

I believe you can look at the issue first-hand on your own machine by going to https://up.codes. I'm using Chrome 71.0.

Why are the CSS files not being cached?

Garrett
  • 4,007
  • 2
  • 41
  • 59
  • I did not understand what is your yuestion and what you need? Nobody will answer you without this. Would you like to write it, please. – Bharata Jan 09 '19 at 09:09
  • @Bharata, ok I've clarified the question at the bottom, thanks. – Garrett Jan 09 '19 at 15:57
  • @Garrett I just checked your site and all your css files were cached just fine on my end. I also get status 304 - NOT MODIFIED for all of them after the first time I've downloaded them. Are you sure you don't have some kind of debug mode set on your end that's forcing all assets to be re-downloaded? I see that your request headers contain "Cache-Control: no-cache"... – m_katsifarakis Jan 09 '19 at 21:17
  • @m_katsifarakis, thanks, I added a paragraph/image to clarify. It sounds like we have the same behavior. I also get a 304 back when hitting the server on the second request, but I don't want there to *be* a request at all. – Garrett Jan 09 '19 at 22:53
  • @m_katsifarakis, the first request indeed has a "Cache-Control: no-cache" because I did a hard refresh (CTRL+F5) for the first one. I could have also just opened Incognito and navigated to the page for the first time ‒ on second request, the problem still manifests. – Garrett Jan 09 '19 at 22:55
  • I still don't understand what you would like to have. Do you want to know why is it happening **OR** (not and) do you want to know how to get that ... [your wish]? After the question was answered you can't ask a second question. Would you like to describe it, please. – Bharata Jan 10 '19 at 00:13
  • @Bharata, I'd like the CSS files to be loaded from memory instead of making a request so that my site will feel faster. I'd like to know how to do that or be told why this is happening such that I can fix it. – Garrett Jan 10 '19 at 00:26
  • What does `(from me...)` mean, is it "from memory"? – David Jan 15 '19 at 09:18
  • On reload I get only the main-url and the google font loaded with 200 everything else with 304 from cache. – David Jan 15 '19 at 10:04
  • you can force your browser to use newest css by adding something like yourfile.css?microtime=23394824 . Is it possible that there is a ? after your css file? –  Jan 15 '19 at 20:11
  • @David, yes, exactly, that is truncated from `(from memory cache)`. Interesting about your reload behavior. So, when you reload, for the `global.css` file, what appears in the "Size" column of the DevTools Network tab? – Garrett Jan 15 '19 at 20:18
  • @User23332, right, that's exactly what I do to enforce using the newest CSS. You'll notice from the DevTools that I have a querystring appended to the CSS (and JS) files looking like: `?v=d04f0cc`. The goal here is for the browser to load the CSS files from cache until that querystring changes. – Garrett Jan 15 '19 at 20:20
  • @Garrett this resource might be useful to you: https://css-tricks.com/strategies-for-cache-busting-css/ –  Jan 15 '19 at 20:27
  • @Garret you should verify it in different browsers, including change of the cache-settings. So it would get a long list if I'd do it and post it then. – David Jan 15 '19 at 20:45
  • @Garret I've noticed this behavior across chrome and safari on multiple sites, not just yours. Cache-control headers all look correct to me, but for whatever reason it's showing a server trip. I don't really understand why, but it seems ubiquitous in my quick look-around. – kyler Jan 15 '19 at 21:54

4 Answers4

4

@Allen found the issue (Vary header included cookie and the cookie was changing between requests), but I'll show how to fix it for the case of Flask for posterity. You can use Flask's @app.after_request() hook to make sure Flask does not add cookie when it hits this line:

@app.after_request
def add_header(response):
    url = request.url
    if ('.css' in url or '.js' in url or '.svg' in url or '.png' in url or
        '.gif' in url) :
        # Flask adds to the header `Vary: cookie` meaning the client should 
        # re-download the asset if the cookie changed.  If you look at the Flask
        # source code that comes next after the below return, it will add 
        # `Vary: cookie` if and only if session.accessed is true.
        session.accessed = False
    return response
Garrett
  • 4,007
  • 2
  • 41
  • 59
  • 1
    you should use nginx as front server to handle these static files. http://docs.gunicorn.org/en/stable/deploy.html – Allen Jan 16 '19 at 16:00
  • @Allen - That's not mutually exclusive with this answer. In my case, I have nginx in front of the flask app configured as a caching, with specific application paths (`/static`, in my case) having a extremely long `proxy_cache_timeout` parameter. That way, you can just use the built-in server for testing, and the deployed version still gets the benefit of having a fast front-end. – Fake Name Feb 02 '19 at 11:55
1

Check out for your web.config's compilation attribute, if its:

<compilation debug=”true”/> 

CSS will get continually downloaded by clients on each pageview request and not cached locally within the browser.

If its set to false, the resource is only downloaded once to the client and cached there.

Check out this post: Chrome will not cache CSS files. .js files work fine

Abhishek
  • 5
  • 6
  • Thanks for the answer! Unfortunately, I'm not using IIS as in the linked answer, but rather Flask (Python). But actually, I think this problem is independent of the server technology. There's an issue with my response header, with Chrome or with my understanding of how caching works. – Garrett Jan 14 '19 at 18:57
1

Chrome uses multiple types of caches.

Blink (the rendering engine that Chrome uses) uses an in memory cache and a disk cache. It uses this cache for images, fonts and js files. As long as a file of that type is still in the memory cache or the file cache it will be loaded from there and skip the WebRequest API, this means that no call is made to the server.

I don't know exactly why css files are not being cached by Blink, but this is the reason why you see an HTTP request for css files and not for js ones.

Note, that if, for some reason, the js file is evicted from the memory cache and the disk cache you will see an HTTP request for the js files also.

Radu Diță
  • 13,476
  • 2
  • 30
  • 34
  • Thanks, that's good to know, especially as a starting point for digging in to the Chromium source code if it comes to that. Strangely, ever other site seems to work fine (for example, Stack Overflow's CSS files say `(from disk cache)` in the "Size" column). – Garrett Jan 15 '19 at 20:29
1

Your server responded with different session cookie when requesting these css files, and your header set with Vary: Cookie, which caused the browser to send request again because of the session cookie change.

Allen
  • 6,505
  • 16
  • 19
  • Thanks, you are right! Indeed the .css requests had different cookies sent while the .js requests sent the same cookie. Not sure why that is, but it was an easy fix to modify the `Vary` header to not have `Cookie` in it which I [show below](https://stackoverflow.com/a/54209333/2223706) for the case of Flask. – Garrett Jan 16 '19 at 01:46