Force Refresh of Cached CSS Data

Force refresh of cached CSS data

TL;DR

  • Change the file name or query string
  • Use a change that only occurs once per release
  • File renaming is preferable to a query string change
  • Always set HTTP headers to maximize the benefits of caching

There are several things to consider and a variety of ways to approach this. First, the spec

What are we trying to accomplish?

Ideally, a modified resource will be unconditionally fetched the first time it is requested, and then retrieved from a local cache until it expires with no subsequent server interaction.

Observed Caching Behavior

Keeping track of the different permutations can be a bit confusing, so I created the following table. These observations were generated by making requests from Chrome against IIS and observing the response/behavior in the developer console.

In all cases, a new URL will result in HTTP 200. The important thing is what happens with subsequent requests.

+---------------------+--------------------+-------------------------+
| Type | Cache Headers | Observed Result |
+---------------------+--------------------+-------------------------+
| Static filename | Expiration +1 Year | Taken from cache |
| Static filename | Expire immediately | Never caches |
| Static filename | None | HTTP 304 (not modified) |
| | | |
| Static query string | Expiration +1 Year | HTTP 304 (not modified) |
| Static query string | Expire immediately | HTTP 304 (not modified) |
| Static query string | None | HTTP 304 (not modified) |
| | | |
| Random query string | Expiration +1 Year | Never caches |
| Random query string | Expire immediately | Never caches |
| Random query string | None | Never caches |
+---------------------+--------------------+-------------------------+

However, remember that browsers and web servers don't always behave the way we expect. A famous example: in 2012 mobile Safari began caching POST requests. Developers weren't pleased.

Query String

Examples in ASP.Net MVC Razor syntax, but applicable in nearly any server processing language.

...since some applications have traditionally used GETs and HEADs with
query URLs (those containing a "?" in the rel_path part) to perform
operations with significant side effects, caches MUST NOT treat
responses to such URIs as fresh unless the server provides an explicit
expiration time. This specifically means that responses from HTTP/1.0
servers for such URIs SHOULD NOT be taken from a cache.

Appending a random parameter to the end of the CSS URL included in your HTML will force a new request and the server should respond with HTTP 200 (not 304, even if it is hasn't been
modified).

<link href="normalfile.css?random=@Environment.TickCount" />

Of course, if we randomize the query string with every request, this will defeat caching entirely. This is rarely/never desirable for a production application.

If you are only maintaining a few URLs, you might manually modify them to contain a build number or a date:

@{
var assembly = Assembly.GetEntryAssembly();
var name = assembly.GetName();
var version = name.Version;
}

<link href="normalfile.css?build=@version.MinorRevision" />

This will cause a new request the first time the user agent encounters the URL, but subsequent requests will mostly return 304s. This still causes a request to be made, but at least the whole file isn't served.

Path Modification

A better solution is to create a new path. With a little effort, this process can be automated to rewrite the path with a version number (or some other consistent identifier).

This answer shows a few simple and elegant options for non-Microsoft platforms.

Microsoft developers can use a HTTP module which intercepts all requests for a given file type(s), or possibly leverage an MVC route/controller combo to serve up the correct file (I haven't seen this done, but I believe it is feasible).

Of course, the simplest (not necessarily the quickest or the best) method is to just rename the files in question with each release and reference the updated paths in the link tags.

Force browser to refresh CSS, JavaScript, etc

General solution

Pressing Ctrl + F5 (or Ctrl + Shift + R) to force a cache reload. I believe Macs use Cmd + Shift + R.

PHP

In PHP, you can disable the cache by setting the expiration date to a time in the past with headers:

header("Expires: Tue, 01 Jan 2000 00:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

Chrome

Chrome's cache can be disabled by opening the developer tools with F12, clicking on the gear icon in the lower right corner and selecting Disable cache in the settings dialog, like this:

Sample Image

Image taken from this answer.

Firefox

Type about:config into the URL bar then find the entry titled network.http.use-cache. Set this to false.

How can I force browsers to reload cached CSS files when using Asp.Net Themes?

I think I have a quick and dirty solution. The trick is to examine the controls within the page header (for example in the PreRender phase), find the links pointing to CSS-files under the App_Themes folder and make them dynamic (by adding some random information to the query-string). This will most likely tell the browser to invalidate the cached version of the file.

The code:

protected void Page_PreRender(object sender, EventArgs e)
{
HtmlLink link = null;

foreach (Control c in Header.Controls)
{
if (c is HtmlLink)
{
link = c as HtmlLink;

if (link.Href.IndexOf("App_Themes/", StringComparison.InvariantCultureIgnoreCase) >= 0 &&
link.Href.EndsWith(".css", StringComparison.InvariantCultureIgnoreCase))
{
link.Href += string.Format("?t={0}", DateTime.Now.Ticks.ToString());
}
}
}
}

The output:

    <link href="App_Themes/MyTheme/MyTheme.css?t=634310637798128189" 
type="text/css" rel="stylesheet" />

Note that you need to have a <head runat="server"> declared in your page's markup in order to be able to access the Header property (otherwise it will be null).

How to force Chrome browser to reload .css file while debugging in Visual Studio?

There are much more complicated solutions, but a very easy, simple one is just to add a random query string to your CSS include.

Such as src="/css/styles.css?v={random number/string}"

If you're using php or another server-side language, you can do this automatically with time(). So it would be styles.css?v=<?=time();?>

This way, the query string will be new every single time. Like I said, there are much more complicated solutions that are more dynamic, but in testing purposes this method is top (IMO).

How to force user to refresh cache

You can't force user's browser to clear cache from your website.
Just change your pdf name and update it's link in your html accordingly when you replace it.
This will prevent browsers from loading it from cache.

For instance, if you have a file named form1.pdf and want to replace it with updated version, delete form1.pdf (don't simply replace), name your new file a different name like form1a.pdf & update existing link to point to form1a.pdf.



Related Topics



Leave a reply



Submit