Is swapCache() required in HTML5 offline apps? - html

If I don't implement any updateready event handler and don't call swapCache(), does that mean that the browser will always use the first (oldest) downloaded version of the application?
If no, then why is the swapCache() method needed?

Swapcache makes sure that "subsequent" calls to cached resources are taken from the new cache.
Subsequent meaning after swapcache.
To see this in action try setting the src property of an img dynamically after the
swapcache call in the updateready event (so that the browser loads it at that particular
time). Make sure this image is not already loaded elsewhere in the page since that will
distort this test.
Now change the image and change the manifest files (to force reloading the cached files).
Reload the page in your browser.
You should now see the new version of the image in your rendered page.
Now comment out the call to swapcache.
Make a change to the manifest file and reload the page and thus all resources.
Refresh the page again (to make sure you have a version from the new cache).
Now change the image again and change the manifest.
Again reload the page: now you see the old version of the image.
In the last case, the browser finished loading the new versions in cache, but since
swapcache was not called, the image was still taken from the old cache.
If you do not do any dynamic loading of resources in your page, the swapcache has no effect.
In particular, if you reload the page in the updateready event handler calling swapcache
first has no effect since reloading the page will get it from the new cache anyway.

I have an app with a pretty large cache (>100mb). This takes a particularly long time to swap the cache in (and pretty much locks the browser while this is happening). So I display a message indicating that the app is updating (please wait...), then call swapCache(), then display a new message when it's done indicating completion.
Not sure if this answers your question (as to why it's necessarily needed), but I think it provides a valid use case for swapCache() at least.

Let's imagine 2 different scenarios.
You call location.reload() when the new content is available. The page will reload using its all-new content. applicationCache.swapCache() is not needed in this case.
Your user continues to interact with your page, without any reload. This interaction causes an asset to load dynamically. For the sake of argument, let's imagine that it's a rollover image, and let's imagine that you have just updated this rollover image. Without applicationCache.swapCache(), your user will continue to see the old rollover image. After applicationCache.swapCache(), s/he will see the new rollover image.
So applicationCache.swapCache() without a reload says: "Keep the page looking the way it was when it was loaded, but use any new assets now, as soon as the page asks for them".

The SwapCache method provides a mechanism for the application to be in control of how an when updates are applied. In regular HTML apps, it can be difficult to determine if the correct JS is present on the clients browser.
Also browser implementations vary on when a cache would be updated, I found the iPhone particularly stubborn. swapCache put me back in control of how my app is updated i.e. I could choose to automatically apply the patch or let the user choose when to apply etc.

I was wondering the same thing. I seem to be able to trigger a successful update by just calling "window.applicationCache.update()". If the manifest file has been modified, the 'download' event is triggered, then eventually the "update ready".
When I reload it, it appears to have been applied. I don't seem to need to call swapCache(). I have provision for calling it from the app, but so far have not noticed any effect on the update process.
Calling update() basically eliminates one reload, AFAICS.

swapCache will switch from the previous set of resources listed in the cache manifest (when the running webapp was loaded) to the new set. You are doing this in response to an updateready after all, which signals that a new manifest has been loaded.
This is not to be confused with loading individual resources, for which the usual browser caching policies still apply. In other words you will swap set of resources, but individual resources need their own cache management to ensure they're reloaded when you need them to.
I haven't tried this yet, but it would seem to suggest structuring the code as an "update controller" javascript file that handles the update process, and javascript sources with a versioned filename (or URL) with known entry points.

Related

Chrome Caching Mechanism

Help me understand what causes this:
And by this, I mean the fact that 100% of my assets are cached but there is still a ~200ms delay between receiving the content from the script and the DOMContentLoaded event firing. This is Chrome on Linux and the page being served up is about 100 lines of divs and things, nothing major.
This 200ms "delay" that you're observing is not caused by the network, but by processing the content.
The delay between fetching the HTML and CSS, and between the CSS files is the time needed to parse the HTML. When JavaScript comes into the mix, the HTML parser halts until the script is loaded and until is evaluated and executed.
You can get a detailed breakdown of what affects the load timing by opening the Timeline tab, clicking on the button/circle in the upper-left corner ("Record") and reloading the page. Below is an example which shows the correlation between script execution time and resource fetching time. These screenshots were recorded in a browser profile without any extensions, if you have installed any extensions, then the times will probably increase.
Network tab:
Timeline tab:
Read more about performance and profiling:
https://developer.chrome.com/devtools/docs/network
https://developers.google.com/web/fundamentals/performance/critical-rendering-path/

If I load content dynamically, does history.pushState() cause that content to be added to the browser cache?

Here's what happens:
Page loads (a timeline view)
User scrolls down to the bottom
More timeline content is loaded via AJAX
The URL is set to a new value with history.pushState(). If this URL is accessed directly, it loads the timeline so that it includes all content that's been loaded dynamically so far.
The user clicks a link in the timeline
The user then clicks the back button in the browser.
My question: when the back button is pressed, will the browser do a fresh load of the url provided via pushState() (which may involve a large performance hit if they have gone a long way down the timeline)? I'm hoping that instead it will update its page cache somehow when pushState() is called to include the DOM with the dynamic content added, and then reload that instead.
If it doesn't do any automatic cache magic like that, is there any way to make it do so in order to improve performance? It seems wasteful to reload a large number of posts every time the user clicks away from the timeline. Also, as they scroll, the URL is constantly updated so it would be a fresh load of all posts every time they click away, not even using normal browser caching.
I've looked for information, but can't seem to find anything that says how pushState() modifies the cache, if at all.

Blank time between resource loading under network inspector

I've been working on a new website and practicing my JS/jQuery/AJaxy skills. Last night I wanted to take a look at how long the page was taking to render and see if there were any areas I could clean up to increase speed. While the page loads in about 200 - 300 ms every time, I'm seeing a large amount of blank space between resource loads under the network inspector.
http://i.imgur.com/7ng6m.jpg
Has anyone else seen this or know what I can do to minimize that time (talking about the blank space between like the html and the first css file)?
Quite possibly it is caused by the extensions you have installed. AdBlock, LastPass and Google quick scroll took altogether about 200 ms on my machine.
Unfortunately, these extensions are invoked on every site and block loading the additional resources.
Try it with out of the box browser setup, the loading time will increase tremendously.
You've got a bunch of images loaded just after the page has been loaded (the load and DOMContentLoaded events have fired - the blue and red vertical lines across the Timeline). I can see that the images are loaded by the JQuery library (the Initiator column), perhaps to build a gallery or something.
So, the case is that JQuery loads the images after the page load, presumably in the onload handler (this can look like $(document).ready(handler) in your code, but other options are possible, too).
The delay between the initial page load and requesting the first resources is almost certainly caused by Chrome extensions. To find the culprit: Record a timeline in the Timeline tab in Chrome Developer Tools; Identify the scripts that are running during the Parse HTML phase; Work out which extensions they're from.
To record a timeline:
Open the timeline tab and click record.
Reload the page and then stop the recording. (A couple of seconds should be enough.)
To find the culprit:
Find the first main Parse HTML block on the timeline. On the row below you will probably see one or more Evaluate Script blocks. These are the culprits.
Click on one of the Evaluate Script blocks and find the script name in the bottom pane. Mouse-over the script name. The tooltip will have the URL of the script, which should be of the form chrome-extension://{long_identifier}/{path}
Memorise the first few letters of the identifier and search for it in the chrome://extensions/ page. This tells you which extension is causing the problem. Try disabling it - you should see a difference.
Repeat for the other Evaluate Script blocks.
In my case, I have 20 extensions installed but only two were causing a delay: LastPass and Fauxbar. I've chosen to leave them enabled because for me the productivity benefit of these extensions outweighs the downside of the added latency.

Preferred way to start a download in a browser

We are currently using a meta refresh to initiate a download on a page, I read on Wikipedia that using this is not UX (user experience) friendly. So what is the way to have a download start after a few seconds when landing on a download page.
User interface-friendly way would:
Not spring an unannounced surprise to the user. So postpone the download by X seconds and clearly announce that.
This is done by setting up JavaScript logic to display a changing countdown to download. See below for details on implementation.
Allow user to control this by allowing immediate download
This is done by having the download timer announcement provide a widget (button or a link) to download immediately.
Keep the current page, by opening the download in a new window/tab.
The "kick off the download" logic should preferably be - instead of the obvious setting of window.location.href - something which opens a new window for the download. This way you allow the user to keep the main download landing page intact.
If possible, present a nice download widget
Instead of just pushing the URL of the download target, consider using custom download wisget like jQuery's jDownload plugin
To implement the changing countdown, do something like this:
Set up a variable for how long till download starts:
var DownloadIn = 10;
Set up a timer in JavaScript using setTimeout()`:
setTimeout("shouldWeDownload()", DownloadIn * 1000);
Subroutine shouldWeDownload() called from a timer will:
check if time period (stored in DownloadIn variable) is greater than zero.
If the time is NOT up (greater than zero), it will:
a. Check if a special "AlreadyDownloading" variable is set to true - this variable will be explained later. If true, simply exit.
b. print to a special DIV on the page - something very obvious and visible to the user - a message "XXX seconds left till the start of download. Click on this link to start the download".
c. Decrement DownloadIn variable
d. Set the timer again using the same setTimeout
If the time's up, kick off the download.
In addition, the "this link" link in the message would also immediately kick off the download. To make things clean, the "immediate dowload" onClick JS handler should set a special "AlreadyDownloading" variable which is checked in the logic above should be set to true, so we don't start a second download due to minor race conditions.
I don’t know of any research on what users expect, but I’d suggest mentioning that it’s a download in your initial download link, e.g.
Download my awesome track
(Maybe style that link like a big button, maybe even with an arrow pointing downwards in it: e.g. something like this.)
And then set your server to return that file with the Content-disposition header set to 'attachment' and the name of the file, so that the browser immediately lets the user know they’re downloading something:
Content-disposition: attachment; filename=kiss_from_a_rose__dubstep_remix.mp3
That way you don’t open a new page just to make the file download. The file downloads, the user’s still on the page where they were when it’s downloaded, everyone’s happy.
Fewer steps = fewer things for users to be confused by.
Using the browser’s UI = more chance that the user will have seen it before, and thus know what’s going on
unix user freindly? Depends entirely on the browser, and last time I checked, most/all linux browsers and safari worked fine with meta refresh.
Which is why most websites offer meta refresh with a download link.

Detect if image is loaded on page

My question is not like this one: Browser-independent way to detect when image has been loaded
I have advertisements on my site for which I get paid per impression, now recently I have seen a dramatic drop in the number of impressions that each ad has been getting however I have been getting more average hits/month. Is it possible for me to detect if an image has been loaded or if something like a 404 (common with cheap ad blockers) has been loaded instead?
How are you counting now? Judging by your question I suspect you're parsing the server log or the images are served via a dynamic url. If this is the case then the drop could be caused by client or proxy caching. Users are viewing the ads but the request never hits your server.
The obvious solution would be to disable caching but this is extremely rude to your visitors. The common approach now is to use a 1px GIF as a beacon to count an ad. JS would work too but you lose hits when JS is disabled.
<div id="ad">
<img src="/real.gif?ad_id=3435">
<img src="/beacon.php?ad_id=3435&random=6354377">
</div>
BTW: If the counting is done by the ad provider then there's always the possibility they are lying. Marketting people aren't generally the most honest or principled of folk.
Often ad blockers is not a reason of "dramatic drop"...
You can add javascript that will "ping" your ad images server or you can check your images to be loaded... Both are very easy to implement, but if it fail it will distrub legal users. For example I hate when pages hang on close, because someone gather staistics and send request to the server in onunload event...
There's a "complete" property added to image tag on IE when the image is loaded.
You can also listen the "load" and "error" events on images.
One way would be to log the image loading using Ajax, using the onload event of the image. If you log page loads the same way, you can compare page loads to page loads that successfully loaded the image.
<img src="..." onload="logMe(this)" />
function logMe(img) {
now = new Date()
src = this.src
....your Ajax code that writes to the server log.
}
1.) There's an onload event for images... you can see when/if this is fired.
2.) You can use the DOM/JS to see if properties on the image exist and match what you're expecting.
3.) Be aware that if the image doesn't have a unique path, or is served up to be cached, that the browser won't re-fetch the image (so repeat visits won't reload images)
For the record, if you are getting paid per/impression you are quite lucky. Most systems only care about the hits. Thus if an image is loaded, it means nothing... but if a user clicks it, then there is compensation.