Workbox's service worker not updating when changed - service-worker

Explanation
I'm having an issue with Workbox where my website doesn't update when a file's content is changed, unless I manually clear storage/site data in my browser.
Since v4 release this year, the cleanupOutdatedCaches, which is in my code, should take care of this, but the problem persists.
Example
I created this website to exemplify. Once you access it, Workbox will install the service worker, but if I change, for example, test1 to test2, you won't see the change, unless you clear the site data in your browser and refresh.
I also tried only unregistering the sw; it shows the updated version (test2), but when refreshing twice it goes back to the old version (test1).
You can see the website's code in GitHub here.
Thanks in advance,
Luiz.

cleanOutdatedCaches will only clean caches created by older versions of the workbox library. In this case, since you are using the same version fo workbox, the call to this method does nothing.
https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox.precaching#.cleanupOutdatedCaches
Once a particular file is precached by Workbox, it will never attempt to retrieve that file from the network, unless the revision you have specified in the precacheAndRoute call is different from what was previously cached.
Since you changed index.html but not the revision in precacheAndRoute, workbox assumes the file is unchanged. So,what you need to do is to update the precacheAndRoute with a new hash that corresponds to the new version of index.html
You can achieve this by either using injectManifest
https://developers.google.com/web/tools/workbox/modules/workbox-build
or any other build tooling you use.
Edit:
You can invoke skipWaiting programmatically as well
https://developers.google.com/web/tools/workbox/modules/workbox-core#skip_waiting_and_clients_claim
But you do need to use it with caution. Here is one way to do it :
https://developers.google.com/web/tools/workbox/guides/advanced-recipes

Related

Service workers checking import script for byte sized difference

I have been checking a lot of threads on this topic , and can't seem to find a clear answer to this .
Question :
Do service workers check imported scripts for byte size difference, and trigger update of SW if there is difference.
In GitHub issues I went through :
Add web SDK API for service worker to be updated manually
Consider relying on eTags (or other headers) for service worker dependencies to check for updates
And also followed up with these :
Jake Archibald's Service worker meeting notes
Service worker: importScripts never updates scripts
Most of the articles are from 2016/17 and they are saying this should be implemented. On GitHub theres even a mention that work on this has started, but nothing more, no clear status on this or maybe I'm just missing it ?
Any info on this would be helpful.
According to this, starting in version 68, chrome will ignore HTTP cache when requesting updates to the service worker script. Requests for importScripts will still go via the HTTP cache. But this is just the default—a new registration option, updateViaCache is available that offers control over this behavior.
Example of updateViaCache option:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js', {
updateViaCache: 'none'
});
}
When set to 'none', the HTTP cache will not be consulted when making requests for either the top-level /service-worker.js or for any imported scripted, such as the hypothetical path/to/import.js.
It's actually the filesize difference in the SW file itself. If you would look at this SW example at line 31, the variable CACHE_VERSION gets updated everytime there is an update. This will enable the browser to dump the old one and get a new version from the server.

Angular 5 ServiceWorker not loading updated ngsw.json

Not sure if this is a potential bug or me doing something wrong.
I'm using cli based app, #angular/serviceworker 5.1.0 #angular/cli 1.6.0
Implementation of the SW is exactly by the book
I will try to describe what's going on:
Consider an app with running service worker. The SW caches data from ngsw.json.
Now, I am going to deploy a new ng build --prod files with new budle hash.
Currently running app's ServiceWorker will be loading old cached files unless explicitly ask to update by SwUpdate service. That's fine.
But here's the thing. Upon opening new tab and loading new instance of the app it still loads the old files. In network log there is no fetch of new ngsw.json.
Do both tabs use the same ServiceWorker?
How does ServiceWorker knows when to check for new ngsw.json?
The most bizzare things:
Sometimes upon hitting F5 the ServiceWorker still loading old files. Sometimes it loads the new files. Sometimes it tries to fetch files with old hash and fails (404)!
I haven't been able to figure out any pattern so far.
Is it possible browser caching is causing problems? I tried to add server response headers to no-cache and expire: 0 but no difference.
At the time of this answer, the latest version of ngsw (#angular/service-worker) is 8.2.13.
Do both tabs use the same ServiceWorker?
Yes, both tabs activate the same service worker. This is done because of data integrity, if you had one service worker processing differently to another service worker across different tabs, this would become a nightmare to maintain.
How does the ServiceWorker know when to check for new ngsw.json?
ngsw.json is updated when you call a production build, as you've identified: ng build --prod. The service worker doesn't consider an update to ngsw.json as an update to the service worker. As such, it can update the service worker's cache without creating a new version of the service worker and a simple refresh should suffice, without needing to close the browser tabs.
If the service worker is updated, a new service worker should get installed but it won't activate until all associated browser clients (tabs) have been closed, which will make it safe to update.
Sometimes upon hitting F5 the ServiceWorker still loading old files.
Sometimes it loads the new files. Sometimes it tries to fetch files
with old hash and fails (404)!
The refresh button doesn't behave ordinarily when it comes to service workers. If you're doing a hard reload, you will bypass the service worker and request new data. This action won't necessarily update the service worker's cache. As a result, you might find the next refresh loads old data, retrieved from the cache associated with the old service worker.
Is it possible browser caching is causing problems?
To manually invalidate the service worker's cache, head into DevTools > Application (tab) > Cache storage and delete its contents.

Service Worker: files are updated on the server but old version showing in browser

I am building a static app with PouchDB on Google AppEngine.
When I open the site in a browser window, it is showing a version I uploaded several hours ago.
If I open the site in an incognito window, the updated version is displayed (therefore I don't think it is actually an error in the console).
I put a new version number in app.yaml
I have migrated all traffic to the new version.
I have cleared my cache, deleted cookies, checked my application data, everything. I even reinstalled Chrome and Firefox.
I updated my Python version and my Google AppEngine Launcher yesterday; the problem pre-dated that update.
Also: just discovered that if I go to the URL of the updated version
http://4.[app-id].appspot.com, it displays the correct, updated version.
This is happening in Chrome, Firefox, and Edge.
Edit: probably should have mentioned that my site uses Service Workers and IndexedDB. I assume my service workers are caching the previous version, but I would have thought that Ctrl + F5 would clear the cache and show the new version.
I think it must be the Service Workers caching the pages (which is, after all, what they are supposed to do). This is actually really annoying when you are developing though.
A guy called Rich Harris has documented this behaviour and some workarounds on a Github Gist.
Reloading the page doesn't behave as you'd expect
If you make a change to your service worker, then reloading the page
won't kill the old one and activate the new one (it detects the change
by requesting the service worker file each time and comparing the old
and the new byte-for-byte), leaving you somewhat confused as to why
your changes haven't taken effect. This is because the old window is
never actually closed, meaning there's never a time to swap them out –
you need to kill the tab completely then reopen it.
Or you can have the browser do that for you by going to the
Application tab in devtools (in Canary, not stable Chrome yet), going
to the Service Workers section, and checking 'Update on reload'.
UPDATE (13 Nov 2017): This functionality is now available in Chrome, so you don't even need to download Canary.
And here's which bits of the application cache to clear:

How to deploy client-side service WSDLs

I have code using the SysOperationFrameworkService, and after a model-deploy or some other set of circumstances, many users get Function SysOperationDataContractInfo::newParameterInfo has been incorrectly called..
It's unable to be resolved with full-compile, sync, full CIL, deleting XPPIL files, deleting AUC/KTI, usage data, security (they're admin), refreshing caches (server &client), etc. and I have a ticket open with Microsoft and they're struggling.
I've narrowed the issue down to when the service group AxClient located in the AOT at \Service Groups\AxClient WSDL files get deployed to C:\Users\[User]\AppData\Local. Either those files existing there, or something happening when those files get deployed is needed.
Any idea how/what causes these files (AxClient.wsdl, etc) to be created? With a user who happens to be "working", I can close the client, delete all the files, open the client, and no files will exist...then I perform a SysOp process and those files get created during that process. With the non-working user, with same security on the same machine does it, the files don't get created.
I have found that the
"Function SysOperationDataContractInfo::newParameterInfo has been incorrectly called" has been throwed because of a possible bug in the kernel when calling the "dictMethod = new DictMethod(UtilElementType::ClassInstanceMethod, dictClass.id(), methodName);" in the SysOperationServiceController.getServiceOperation() method. In my case the new DictMethod was sometimes unable to get the method parameter from a superclass, causing the _parentMethodParameterName check fail in the SysOperationDataContractInfo.newParameterInfo.
So, I solved the issue just by doing an override of the super method where the parameter could not be retrieved and then just calling super(_parameter), then everything went well.
Have you tried axclicfg.exe -> connections -> refresh

Why am I getting the message "The specified request cannot be executed from current Application Pool"?

Quite not sure why I see this error.
I navigate to my Login View like so http://test.staging.com/mywebsite/Login
My Login view was just redone using MVC but I have seen this same error message going to an aspx page as well...
If I use http I get the error message The specified request cannot be executed from current Application Pool.
If I use https://test.staging.com/mywebsite/Login, I'm good.
If I don't specify a protocol, test.staging.com/mywebsite/Login, I get the error as well
Is there an error happening under the covers and my custom error page can't be shown like discussed here?
What are some other causes of this error?
That usually means your custom errors are configured to run as a different AppPool.
You can read more at MSDN. (See section "Using Custom Errors from Another Application Pool").
There are two ways to correct this behavior. The first is possibly not one that you are interested in because it would require you to change your current architecture and run both sites in the same application pool (such as share the same worker process memory space). To do this, simply move the /errors virtual directory to run in the same application pool as the site for which it serves the custom error.
The second way is to make use of a registry key provided by IIS 6.0. This registry key makes sure IIS 6.0 does not check the metadata during the execution of the custom error and therefore allowing this to work.
See the article for information on the registry key fix.
It may also mean that you are using something along the lines of Server.Transfer to a page that is in a different AppPool.
It could be because you're using different versions of ASP.NET for one or many apps in the pool.
Make sure all apps in the pool use the same version of ASP (e.g. ASP 2.0.50727)
If you just added a new app, try changing the app momentarily to a different version of ASP, then back to same version. I experienced an issue where the displayed version was correct, but under the hood, a different version was used!
Check your event log, under Application, to get more details about the error.
The message would be caused by your page server-side redirecting to a page served by another application pool. Such as for example, in your link, the error page.
I know this is an old thread, but I stumbled upon it and found a different solution. Here's what worked for me: Make sure your application handles .asmx files correctly
From IIS:
Right Click on your project > Properties > Configuration
If necessary, add the .asmx file extension that maps to the aspnet_isapi.dll
Limit to: "GET,HEAD,POST,DEBUG" and restart.
Because I can't comment on vcsjones's answer, I'll add it down here. The DWORD value IgnoreAppPoolForCustomErrors needs to be set under HKLM\SYSTEM\CurrentControlSet\Services\W3SVC\ Parameters vs HKLM\SYSTEM\CurrentControlSet\Services\W3SVC referenced in that technet article. Set it to 1 and do an iisreset and you're good to go.
Source Blog Post
In my particular case, I received this error while trying to serve a content (non ASP.NET) website while it was an Application. Right-Clicking the virtual folder and removing the application fixed it for me.
In my case the application used the application pool that didn't exist. I have no idea how it's happened.

Resources