I'm currently working on an Angular-PWA and am struggling with a Service-Worker/Caching issue.
Basically, we're using the Service Worker to cache the majority of app files upfront on first load. We are then using lazy-loading to retrieve other icons and images when navigating to a page that requires them.
So far everything seemed to be fine, except when I began testing its offline capabilities. When checking 'Offline' in DevTools, most of the app is still served and can be used and navigated etc, except for the missing icons and images that cannot now be retrieved. This is fine, as we're lazy-loading, it's expected behaviour.
But, after un-checking 'Offline' and re-connecting again, if I load a page that I hadn't viewed while offline, it's resources are retrieved as normal. Yet, if I then return to a page that I did previously view while offline, it does not retrieve its missing resources and maintains its bare-bones-media-less version.
Is there a way of storing instances or references to the 'Loading chunk # failed' errors, and when a Navigation event occurs to a page where an error was thrown, maybe just display a dialog and force a location.reload(true)?
If there's anyway to do this in an Angular friendly way, do they provide any functionality to hook onto 'Loading chunk # failed' errors, and be able to store information from it?
What I think I'm after is, a way of storing error information from the Service Worker, then on Navigation events, check that information to see if it refers to the page I'm about to load, if so, load from server, if not, from cache.
So a network-then-cache policy if there are errors, normal cache policy otherwise.
Concept question, shouldn't think any of my code is required, if it is just say, any help is very much appreciated :)
Thanks guys!
Related
I am trying to create a 3d model viewing website for various student projects. Currently pulling from the 3js library to reference OBJs and MTLs on server. The idea is that you can click on the left box of each student wrap div to open a modal with a 3js file viewer.
This works 100% of the time the first time you view a model (first execution of render function), but opening and closing models will often result in MTLs being dropped, see here. Testing on multiple devices it seems that devices with faster internet connection/more processing power can actually load more files before corruption begins. In addition, not rotating the viewer seems to allow more files to be opened.
No error messages for the JS can be found in the Inspector. Messages sent from the 3js library files, however, show numerous errors any time a second/third/nth file is loaded without JS refresh. Putting in location.window.reload() in the exit function refreshes JS each time and fixes the error, but that causes a whole other set of problems.
The site with all source code and files can be accessed here: biszweb.
I will be able to provide more information is needed.
Please advise and thanks in advance.
Resolved. Certain parts of 3.js need to be reloaded after rendering a model. Simple fix would be to insert a js reloading script.
My website is refreshing randomly by itself with an additional unknown URL parameter ?mn followed by a Hash. Example:
?mn=l4ehjinilk0ids2leotmtyrmttfuq4oqedu.eebubnay47ddfhvd
I really don't know where it comes from. It happened even in Incognito mode.
Website is on Sitecore.
Any ideas?
If the page is loading correctly from the server but then refreshes with additional parameters in your browser, it must be triggered by JavaScript code. It can be caused by your own JavaScript, scripts injected by a third-party snippet, scripts executed by your browser extensions and so on.
Follow the steps below to find what triggers this refresh:
Open Developer Tools in your browser and navigate to the Network tab
Select the Preserve log checkbox
Reload your web page to replicate the issue
Find the request with parameter ?mn= and select it
Go to the Initiator tab, it will show the request call stack or request initiator chain similar to this:
This can help you understand what in your browser triggered the web page refresh.
Thank you.
I finally found out.
It was due to the Zoom application, a Post-attendee URL was set, as soon as a meeting is done, Zoom triggers the default browser and redirects to a website.
Background:
I have built an offline HTML5 application that stores some data into the local browser db using pouchdb.
Now the requirements have changed and I have to store large pdf documents(around 200 of them, each with 5mb - 8mb size) into the local browser so the user can view it offline when required.
Issue:
I don't think that it is a good idea to put these large documents received from server into my in browser database using pouchdb.
I would like to know if there is a way to put these documents into my device some how and then get a url reference pointing to the location within the local device ?.
Include the PDFs in your offline manifest, so that they're cached with the rest of the application. Then you just use your normal URL to refer to it, and it's satisfied from the offline app cache.
Re your question below:
When the application is loaded in the browser then i store the details of the associated pages into the browser via a manifest file. And when the user clicks on a 'SYNC' button then I communicate with the server and fetches all the pdfs associated with the user. If I have to persist these pdfs using the manifest then how can I do it ?.....the manifest is already stored
The way we do something similar is this: We have separate pages for the things that the user has taken offline (a day's worth of appointments, for instance), and a list page driven entirely by client-side data that lists those pages. Here's how it works:
When the user wants to take something they're looking at offline, they click a button which opens a URL with the information telling the server what they want (say, example.com/offline/stuff-saying-what-they-want-here/), and the server generates a page with that data embedded in it along with a manifest for the page and any assets it requires. So at that point, that information is available offline on that URL. When it loads, the page registers itself in a list in localStorage, giving a description of the page and its URL.
The list page (say, example.com/offline/list/) has its own manifest and assets, which don't change often because it's driven entirely by that localStorage information. It shows the list of things they have offline with links to them. It's primarily a convenience for users, in case they forget to bookmark the individual things they take offline; e.g., the idea is that they'll bookmark the list once, and never have to worry about bookmarking individual pages. (They could go hunting through their history, but it's a pain.) The list page keeps itself up-to-date by getting the list of known pages from localStorage when it loads, and subscribing to the storage event so if you load other pages in other tabs while the list is open, it sees them arrive and updates its list.
So without knowing anything about your app, it sounds like perhaps your main page could be like or list page, and clicking "sync" could open a page for the PDF, generating the manifest on the fly, and that page could register the PDF in localStorage the way we do with our offline pages so the main page can show their status correctly.
Obviously, there's potential there for the actual appcache and our localStorage list to get out of sync; we can't help it if a user clears appcache (which would make us list things that can't really be viewed offline) or clears localStorage (which would make is not list things they could view offline), but there we are. Users mostly don't do that, all that often.
In the future, you'll get much more granularity and control with service workers, but for now since service worker support is very thin on the ground so far, we're stuck with appcache and its fairly stodgy way of defining offline assets.
T.J. Crowder is right: if your PDFs are static and known in advance, then AppCache is the way to go. Unfortunately it does mean that each and every PDF will be saved in the user's browser when they first load the site, but maybe that's what you want.
Else if the PDFs are dynamic and not known in advance, then yeah, you may see performance problems from PouchDB with 5MB attachments. But if you want to try it out, then check out PouchDB attachments and blob-util. blobUtil.createObjectURL() is exactly what you're looking for in terms of a "local URL."
I am building a simple website that needs to be able to run completely offline if needs be. With the intention of being a 50+ page searchable reference manual.
I need the whole site to be cached upon opening one page. I'm doing this with the appcache manifest and getting the site to cache and be viewed on an offline mobile seems to work ok.
The site has a basic JavaScript search facility (that was a freeware download) and while online this search works perfectly. As soon as the internet connection is stopped and the cached version is used the search no longer works, displaying one of two symptoms 1. Button is clicked and nothing happens or 2. A 'webpage cannot be found' kind of error is displayed.
Quote from https://developer.mozilla.org/en-US/docs/HTML/Using_the_application_cache#Gotchas
Never access cached files by using traditional GET parameters (like
other-cached-page.html?parameterName=value). This will make the
browser bypass the cache and attempt to get it from network. To link
to cached resources that have parameters parsed in JavaScript use
parameters in the hash part of the link, such as
other-cached-page.html#whatever?parameterName=value.
But that is exactly what your js-search does. It tries to load the subpages like this "http://www.filemanage.co.uk/offline/index.html?1350563635665" using XHR.
As a fix try this
// change in function sendRequest line 228 from
this.httpRequest.open("GET", uri+"?"+q, true);
// to
this.httpRequest.open("GET", uri, true);
I've created a web app that caches all necessary code and data for use offline through applicationCache. However, every time the app starts up, it immediately tries to check for updates. This blocks the browser for a significant chunk of time, even if it doesn't find anything to update. This behavior is highly disruptive to the app (shouldn't updates be done in the background, anyway?). Just the checking stage takes a lot of time on a mobile device, and if it find updates all bets are off as to how long downloading will take (b/c it has to redownload all files) - which also freezes up the browser.
So, I am wondering:
Is there a way to delegate applicationCache updates to a shared Web Worker? OR
Is there a way to block all applicationCache updates until the user specifically wants to check for updates and presses a button that will initiate updates through applicationCache.update()? OR
Are there other ways to mitigate the time spent on checking for updates?
Shouldn't application cache updates run asynchronously in the background?
edit: perhaps a carefully-constructed cache-control header on the manifest file is the answer? I'll be investigating this, but I hope somebody can give me more info on these updates. Thanks.
UPDATE
Ok, I've played with headers, and nothing has helped. I'm starting a bounty. If you can help, please do!
If you want to give the user more control over the actual update, you could parameterise the manifest URL with something specific to that user. Then when the user wants to update, you fire off a request to the server which rolls that particular user's manifest file, and then reload the page client-side to force a reload of the manifest.
I've since been doing some reading and came across this article which seems to be a much more elegant solution if the user is already on the cached page -
http://www.html5rocks.com/tutorials/appcache/beginner/#toc-updating-cache
As for the load time involved in the manifest up-to-date check, that's not something I've ever had a problem with. My understanding was that it happens in the background, are you just concerned about the browser showing loading hints?
The abort() method may be the answer...someday, but I haven't come across any browsers that implement it yet.
I had a similar problem, and tried everything, including the wild idea of putting the manifest inside itself to see if it would cache itself. So I could do the updates manually with ajax requests and eval'ing javascript stuffed into localStorage...yikes.
Finally, I created a very simple html page with a simple manifest. When I tested it, the UI didn't lock up. Slowly I started to add things into the page, and play around with the manifest contents to see what things might cause it to freeze during the applicationCache check. I finally got failure when I added an image to the page, but left it out of the manifest -- that's when the UI started to lock up again. I went back to my original project, and found a few images that needed to be in the manifest, and that fixed the locking UI issue there too.
The checking phase of the applicationCache tries to be asynchronous (at least on the devices I've tested). However, if there are any files missing from the manifest, then everything must wait for the applicationCache to finish checking.
It appears that when the browser needs a file that has not been cached, it waits for the applicationCache to complete the update before it will make a request for the file -- which kind of makes sense, since other resources may rely on the missing file. This puts the brakes on the rendering and makes the UI freeze up. If the manifest is unreachable (e.g. on a different network), the UI can be locked up for about a minute.
To find the files that need to be added to the manifest, watch the server logs as you refresh the app a few times. The suspects will be any GET requests for files other than the manifest.