HInclude Caching problem on Internet Explorer - javascript

I've been using HInclude (http://www.mnot.net/javascript/hinclude/) for sometime now and its working great, but there is one problem though. The part of my site which is fetched using HInclude doesn't get refreshed everytime I hit the back button in Internet Exploer (6.x + and 7.0 also). It works fine on other browsers. I've tried setting the cache-control and pragma controls in header to "no-Cache". but even that is not working. I want HInclude to pick up new content everytime a user clicks back button or re-visits a page with hx content on it. How do I do that?

did you try to put some random string in the end of your JS link ?

A full traffic capture would be useful to see exactly what your server is sending. Having said that, the IE team did work in IE9 to help ensure that hitting the Back button wouldn't hit the server, as allowed by RFC2616 and as implemented in other browsers.
Prior to IE9, the back behavior was pretty screwy/buggy and whether the server got hit could depend on whether the page had explicit caching directives and what the user's IE cache settings were (see midway through this document). In practice, the server was hit much more often than it should have been (which is, of course, never).
If I recall correctly, I think one of the pre-IE9 bugs was to that if the caching headers contained must-revalidate, the client wouldn't pull the file from cache.
-Eric

Related

Why doesn't Chrome re-validate in-memory cache when doing a "normal reload?"

First, I found some resources online here and here saying about the same thing:
For a normal/soft reload, the browser will re-validate the cache, checking to see if the files are modified.
I tested it on Chrome. I have a webpage index.html which loads a few javascript files in the end of body. When hitting the refresh button (soft/normal), from the network panel I saw index.html was 304 Not Modified, which was good. However, all the javascript files were loaded from memory cache with status code 200. No revalidation!
Then I tried modifying one of the javascript files. Did the soft reload. And guess what? That file was still loaded from memory cache!
Why does Chrome do this? Doesn't that defeat the purpose of the refresh button?
Here is more information about Chrome's memory cache.
This is a relatively new behaviour which was introduced in 2017 by Chrome browser.
The well-known behaviour of browsers is to revalidate cached resource when the user refreshes the page (either by using CTRL+R combination or dedicated refresh button) by sending If-Modified-Since or If-None-Match header. It works for all resources obtained by GET request: stylesheets, scripts, htmls etc. This leads to tons of HTTP requests that in the majority of cases end with 304 Not Modifiedresponses.
The most popular websites are the ones with constantly changing content, so their users tend to refresh them habitually to get the latest news, tweets, videos and posts. It's not hard to imagine how many unnecessary requests were made every second and as it is said that the best request is the one never made, Facebook decided to address this problem and asked Chrome and Firefox to find a solution together.
Chrome came up with the described solution.
Instead of invalidating each subresource, it only checks if the HTML document changed. If it didn't, it means that it's very likely that everything else also wasn't modified, so it's returned from browser's cache. This works best when each resource has content addressed URL; for example, URL contains a hash of the content of the file. Users can always overcome this behaviour by performing a hard refresh.
Firefox's solution gives more control to developers, and it's on a good way to be implemented by all browser vendors. That is the new Cache-control directive: immutable.
You can find more information about it here: https://developer.mozilla.org/pl/docs/Web/HTTP/Headers/Cache-Control#Revalidation_and_reloading
Resources:
Facebook's article about the motivation behind proposed change, numbers, comparisons: https://code.fb.com/web/this-browser-tweak-saved-60-of-requests-to-facebook/?utm_source=codedot_rss_feed
Chromium team introducing new behaviour: https://blog.chromium.org/2017/01/reload-reloaded-faster-and-leaner-page_26.html
Browser caches are a little more complex than simple 200 and 304s than they once were and pay attention to server side directives in headers to tell them how to handle caching for each specific site.
We can adjust the browser caching profiles using various headers (such as Cache-Control) by specifically setting the time before expires you can tell a browser to use the local copy instead of requesting a new fresh copy, these can be quite aggressive in the cases of content you really don't want changed (i.e a companies logo). By doing something like Cache-Control: public, max-age=31536000
Additionally you can also set the Expires header which will allow you to almost do the same as Cache-Control but with a little less control. It just sets the amount of time to pass before the browser considers a asset stale and re-requests. Although with a re-request we could still get a cached result if the not modified response code is sent back from the server.
A lot of web servers have settings enabled to allow more aggressive caching of certain asset files (js, images, css) but less aggressive caching of content files.

AJAX activities disappear when browsing forward and back

This is not a Meta question.
I am trying to technically understand what principle is hidden behind the following behaviour. It's very easy to reproduce:
Vote up/down anything on this page1,
Click on any other link on this page,
Come back by pressing the back button.
Your upvote is not there anymore as well as any AJAX activities having appeared on the page.
Why is that? Why is the browser acting like so? How could StackOverflow prevent that?
1 If you are not connected, just wait for someone else's activity on the page (new comment, answer, vote) before moving page.
It’s the browser’s cache that is at play here.
Since you’re asked how SO could “prevent” this, it could be done by advising the browser to check for whether the document has changed every time. But SO not doing so, for performance reasons. So the HTML document is seen as “still valid” for a certain amount of time, during which the browser takes it straight from its cache, without making a round-trip to the server.
If you look at the HTTP response headers in your browser’s developer tools for the request your browser made for this page, you will see something like this,
Cache-Control: public, no-cache="Set-Cookie", max-age=60
– so this HTML document is to be considered valid for 60 seconds. If you navigate away from it and back in your browser, or close the tab and reopen it from history, within that 60 seconds, the browser is supposed to take the cached version of it and display it, without checking again with the server whether or not something has changed. And since your vote did not manipulate this original HTML document (only the DOM was updated with your vote), you still get the previous vote count shown.
But if you press [F5] in your browser, the cache will be circumvented – it will request the document from SO again, and then you see your vote, because this time the updated numbers are part of the updated HTML document that SO serves you.
If you want to delve more into HTTP caching, some resources of the top of Google that seem worth a look:
Caching Tutorial for Web Authors and Webmasters
A Beginner's Guide to HTTP Cache Headers
You are not "unvoting", you just are not seeing your vote because your browser is caching the ajax request.
If your press F12 on Chrome, click on Settings icon and then "Disable cache (while DevTools is open)", when you press back the browser will resend the request.
To prevent that you must specify on your code that you never want that specific request to be cached.
You may want to check the following post:
Prevent browser caching of jQuery AJAX call result
-
Ps. You must stay with the Console (F12) opened while doing the test.

Chrome: disable pre-render of hash change

We're developing a web application that handles state change via change of the hash of the page (e.g. example.com/#/page1).
Lately, I've been running into an issue with Google Chrome, when the prefetch option is enabled ("Predict network actions to improve page load performance"). Among the different routes, we have #/logout that performs the logout.
In the "normal" state, I'm on the page example.com/#/ (the main page), and as I start typing "l" after that (example.com/#/l), Chrome autocompletes with logout. However, not only it does autocomplete, but it also calls the "haschange" event, so the client is sending a request to log out to the server... Even just by typing a l!
This behaviour is not only unexpected, but it's also dangerous. Aside from unchecking "Predict network actions to improve page load performance" in the settings page (which is on by default), is there a way to prevent Chrome to do this?
EDIT
A small new "discovery". Actually, Chrome is not firing the "hashchange" event, as a console.log in the event handler is not being executed. Chrome learnt that, when visiting the #/logout page, a request to the server (GET /auth/destroy) is called, and so it's firing it by itself! What can we do to stop this?
Answering my own question. This is not really a solution, but rather a workaround.
According to this documentation, prendering is disabled in certain situations: with POST requests (not an option in our case) and when the resources are served via HTTPS.
Since we were already going to enable HTTPS in the production environment, we just enabled it in the development one as well and the issue disappeared. However, I still feel like this is more of a workaround than a real solution.

Chrome History API problems

I'm having problems with a website is Chrome.
Most of the site uses ajax/xmlhttprequest for pages loads and the history API to enable the back button. Only the page content is changing with the request, the menu etc are never reloaded. This just re-reuns the ajax request for the previous page. This all works fine until someone clicks the back button after viewing the blog. The blog isn't loaded with ajax, it's just a standard link.
In Firefox if I go to the blog then press back the site loads correctly. The main page with the navigation loaded and so is the page to be viewed within it.
In Chrome however if I press the back button from the blog the 'outer' page isn't loaded, only the contents of the ajax request is. You may need to view it to fully understand.
Is this a bug in Chrome or my work? It seems I can't return to a page that was partially loaded using xmlhttprequest as only the requested item is loaded.
The site is here: http://www.basmooarc.com
Thanks
Ric
short answer
Add a Cache-Control: no-store HTTP header for XHR responses.
long answer
I'm pretty sure this is a bug in Chrome. I found the exact same bug in my app, and it works fine in Firefox but breaks in Chrome. I think the issue is that Chrome caches the XHR response and serves it from the cache when you press the back button. My app uses Etags, but Chrome does not bother to check the Etag. It just uses the cached response, which is missing all the outer content. The best solution I've come up with so far is to add no-store to the cache control header for XHR responses.
You can see the behavior through Chrome's net-internals page. Type chrome://net-internals in the URL bar, open the Events tab and go through the steps to reproduce your bug. When you go to a non-ajax page and then press the back button, you'll see a URL_REQUEST entry for the URL of the page you're trying to go to, but Chrome just checks the cache and that's it. Contrast that with a normal request for that URL. The normal one will have a cache check, followed by an HTTP_TRANSACTION_SEND_REQUEST section, which is where Chrome makes the actual HTTP request.

Detecting if a browser's cache is full

We've identified that full browser caches are the cause of a problem on our extranet. It only affects a small number of our users, but we'd like to alert them to the problem and give them some guidance on how to fix the problem for themselves.
We'd like to use a similar system to the one which GMail uses. When it detects that your browser's cache is full is not behaving as it should, it shows a warning message telling users that their cache is full and that it may cause problems with GMail, along with a link to a Gmail Help page on clearing your browser's cache.
Does anyone know if there any resources out there, or examples of how to use JavaScript to detect that the browser's cache is full behaving badly?
Thanks.
Clarification: What we're actually trying to detect, I suppose, is not whether or not the cache is full, but rather whether a script, which we have configured server-side to be stored in the cache, is being re-requested from the server - in such a way that the browser is behaving strangely, or as if its cache is not behaving as it should.
Further Clarification: Thank you all for the updates on caching. Our scripts are being sent with the correct headers, and we're only seeing this problem in IE6 and IE7 - Mozilla and WebKit browsers seem to be unaffected - but I'm still not sure on how exactly we'd go about using JavaScript and/or XmlHttpRequest to check to see whether or not an object was retrieved from the cache, thus letting us check whether the cache is behaving badly.
The browser's cache will not cause problems if it is full... with a few minor notes.
If the browser cache is full, the browser simply has to download fresh content vs. pulling it from its local cache. (e.g. is slower)
If the browser cache contains invalid data (e.g. an old copy of a JavaScript file) then yes, you may encounter issues. (not because the cache is full, but because you didn't serve up a fresh file for the user (Google for: expires headers and how to alter the URL path to your files when you make script changes to ensure you "break" the cache))
In Internet Explorer, when you push a download file (e.g. an Excel spreadsheet) to the user it must go into the cache to work (an IE bug) - I'm not sure if the file is bigger than the users' total cache, if that causes issues with the file being stored, and therefore loaded (Stackers pls feel free to confirm if this one way or another)
Update:
Based on your clarification, you need to ensure that any script you send to the client is appropriately cached... which means:
Change the URL to your scripts when you want a new version to be downloaded (e.g.)
http://example.com/scripts/latestThing.js?ver=3425
where the "ver" is pulled from your versioning system to ensure you always force the browser to download a fresh copy any time you change your script.
Once you are sure that the URL changes, you can send cache headers that tell the browser to cache the files for a very long time (e.g. your JS Library files (e.g. jQuery) likely don't change every hour, day, week or even month)
This will probably not work as is. But its just an idea:
var img = new Image();
(new Image).src = "imageWithFarFutures.png";
window.onload = function(){
document.getElementById("someIframe").src = "imageWithFarFutures.png";
// NOW if the server DOES get a FRESH request for "imageWithFarFutures.png"
// wouldn't it mean that the browser has kicked it out of its cache?
};
Consider sending a header to have your application never cache your content and to have it expire immediately.

Categories