12

This drives me crazy. Every browser and device has it's own way to clear the cache and reload the .js and .css files. For example, the only way I can get do this in Chrome is to go to go to my login page, do an F12 to load the debugger and proceed. This seems to be the only way to do it windows.

On the old safari in windows you could do it from the menu, as you seem to be able to do in Safari on the IMac desktop.

But how do you do in on the IPhone or IPad??????

I am using the IMac to debug the phone, but no matter how I do it, the .js file stays the same. When I look on the website at the page, the changes are there.

I have tried crashing the phone, double tapping the refresh button, putting it in private mode and back. Nothing works. What was interesting was that I tried it in private move and in the Develop menu I could see two versions of the .js file - one with the changes and one without. When I went back to the non-private mode, the old .js files (no changes) were there.

I also tried to delete the website data for my site and that didn't work.

Anyone know how to do it??????

Thanks,

Tom

tshad
  • 335
  • 2
  • 4
  • 18

6 Answers6

7

Append a query string when including your JS or CSS and change it when you update the code. It will invalidate the cached local versions of this file.

<script src="test.js?1234567"></script>

It's common to use a timestamp.

Mike L.
  • 148
  • 1
  • 7
4

2 answers:

First Answer: Hit the tabs icon, then select Private and paste&go the URL if you only need to force refresh the one time. The Private session will never have a cached version of anything unless it is cached at an intervening proxy. Of course it will cache subsequent requests for the same file. You can close the Private session and create a new one, which is roughly on par with the annoyance level of switching to/from the Settings app.

Second Answer: If you are a developer and you're using Apache, you can set up an .htaccess file like so:

<filesMatch "\.(html|htm|js|css)$">
  FileETag None
  <ifModule mod_headers.c>
     Header unset ETag
     Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
     Header set Pragma "no-cache"
     Header set Expires "Wed, 21 Oct 2015 07:28:00 GMT"
  </ifModule>
</filesMatch>
Wil
  • 757
  • 9
  • 12
3

I've found this solution works for iOS Safari and other browsers ...

It performs a window.location.reload(true) to force the page to reload avoiding use of caching whenever it detects that the cached web app or web page does not match the server's version.

You really want this mechanism in place before you publish the first version of your site as otherwise once it's out there you can no longer rely on ever upgrading your iOS users. This is a nightmare if you rely on client app and server versions being in sync. Sigh ... Sadly it seems Safari and iOS Safari in particular is eager to take the throne once held by Internet Explorer.

During deployment

  • Increment and save a build number.
  • I use a version.json file that looks like {"major":1,"minor":0,"patch":0,"build":12}
  • Copy version.json to both client and server apps.

On server:

  • Write a server API in PHP/Node/Ruby/C# that returns the server's version.json
  • Use web server rules and response headers to prevent API results being cached.

In client app or web page:

  • To diagnose issues, display the client version + client and server build numbers.

Call on page load ...

function onload() {
  var clientVersion = require("./version.json");
  // Might replace axios with new fetch() API or older XMLHttpRequest
  axios.get("/api/version").then(function(res) {
    var serverVersion = res.data;
    var lastReload = parseInt(localStorage.getItem("lastReload") || "0");
    var now = new Date().getTime();
    if (
      serverVersion.build !== clientVersion.build &&
      now - lastReload > 60 * 1000 // Prevent infinite reloading.
    ) {
      localStorage.setItem("lastReload", now);
      window.location.reload(true); // force page reload
    }
  });
}

You might prefer to test serverVersion.build > clientVersion.build rather than serverVersion.build !== clientVersion.build. The benefit of testing !== is that it allows you not only upgrade the version but also roll back a version and ensure clients get rolled back as well.

In the event that the client and server build numbers are mismatched I prevent the client from infinitely reloading by only performing a single reload within 60 secs.

Note that this method is only concerned with matching build numbers (= deployment number) you might prefer something more sophisticated.

Here's a simple node app to increment a build number.

const APP_DATA = "../app/src/assets"; // client folder
const FUNC_DATA = "../functions/data"; // server folder

var log = require("debug")("build:incr");
var fs = require("fs");

function readJson(path) {
  log(`Reading: ${path}`);
  const text = fs.readFileSync(path);
  return JSON.parse(text);
}

function writeJson(path, json) {
  log(`Writing: ${path}`);
  fs.writeFileSync(path, JSON.stringify(json));
}

let version = readJson("./version.json");

version.build++;

log("Version = ", version);
writeJson("./version.json", version);
writeJson(`${APP_DATA}/version.json`, version);
writeJson(`${FUNC_DATA}/version.json`, version);
Tony O'Hagan
  • 21,638
  • 3
  • 67
  • 78
  • 1
    Nice solution. Unfortunately, it seems that passing an argument to `location.reload` is deprecated. https://stackoverflow.com/questions/55127650/location-reloadtrue-is-deprecated – Rick Mohr Oct 13 '20 at 19:35
2

In iOS 10, you can clear the cache by going to Settings > Safari and clicking the "Clear History and Website Data".

For me, this is a bit overkill as I don't want to delete everything for every site. So, what I do is browse directly to the js or css file and reload it if it is the older, cached version.

Rockadile
  • 21
  • 4
  • I also don't want to clear everything for every site. I am debugging my app and making a change. I just want the .js and .css files for my app/pages refreshed. – tshad Apr 18 '17 at 06:21
  • 3
    @tshad This has been addressed in iOS 11. You can now go to Settings > Safari > Advanced > Website Data. This allows you to clear the website data for individual domains. – Rockadile Feb 12 '18 at 21:05
  • 1
    In my case I couldn’t even find the individual website data so browsing the css file directly was a great trick to force Safari to refresh its cache of that style sheet. Worked a treat. Upvoted. – BartmanEH Jun 21 '18 at 02:18
2

I don't think there is a "easy" way to do this. I've tried all of the above including modifying css and js query strings. The closest thing that works is in Rockadile's comment.

Open Setting--Safari--Website Data

Then clear the site you are trying to refresh

Tip: If you are debugging a page use the IP Address then it will show up at the top of this list. Keep both safari and the Website data open so you can toggle between the two.

This isn't as simple as ctl-F5 but is certainly less intrusive than clearing the entire browser's cache.

gritware
  • 81
  • 4
1

Goto Safari -> Preferences -> click the Advanced tab at the bottom of the Advanced tab click the checkbox that says "Show Develop menu in bar" and close Preferences. Then you can open the Develop menu in the program bar that has Safari, File, Edit, View, etc... in it, and click Empty Caches.

Kyle Richardson
  • 5,567
  • 3
  • 17
  • 40
  • 2
    I tried that. I have been trying to do all combinations of stopping and starting safari on both the IMac and the IPhone and selecting the Empty Caches but can't seem to figure out what works. I do it enough times and eventually it gets refreshed. But it is very frustration to take 20 minutes each time I make a change to get the cache refreshed. – tshad Apr 18 '17 at 06:16