I have seen that other similar questions have been asked, and that the error was having the analytics code in the main js file rather than the service-worker.js file. In this case all the code is in the service-worker.js file.
Setup: node 16.0.0 (also does the same with node 15.x.x), and static site built with eleventy
For google analytics I use the analytics.js file. Basically this with a few other options added:
<!-- Google Analytics -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
<!-- End Google Analytics -->
The service-worker.js code in question:
import * as googleAnalytics from 'workbox-google-analytics';
googleAnalytics.initialize({
parameterOverrides: {
cd1: 'offline',
},
});
The service worker in general works absolutely fine. It has various routing routines, precache etc., and the google analytics code seems to do what it should. I can see items caching in IndexedDB when offline, and then the queue clearing when connectivity comes back. I can also see on my google analytics page hits for 'offline' as detailed in the parameterOverrides in the code above.
...so all would seem well, but in the console I still get the following:
service-worker.js?hash=4f292a2050:4259 Uncaught (in promise) TypeError: Cannot use 'in' operator to search for 'sync' in undefined
at Queue._addSyncListener (service-worker.js?hash=4f292a2050:4259)
at new Queue (service-worker.js?hash=4f292a2050:4077)
at new BackgroundSyncPlugin (service-worker.js?hash=4f292a2050:4341)
at initialize (service-worker.js?hash=4f292a2050:4515)
at service-worker.js?hash=4f292a2050:4647
at service-worker.js?hash=4f292a2050:65
I have not run the service worker through terser yet, so it is readable for anyone who wants to have a look.
https://www.thetestspecimen.com/ (then look in dev tools-->application-->service-worker.js)
I should also note that if I use the standard:
googleAnalytics.initialize();
it still does the same thing.
Obviously something is amiss, but I can't figure out what. Any suggestions appreciated
I have seen that other similar questions have been asked, and that the error was having the analytics code in the main js file rather than the service-worker.js file. In this case all the code is in the service-worker.js file.
That is, in fact, what's going on here. The HTML for https://www.thetestspecimen.com/ includes
<script async="" defer="" src="/service-worker.js?hash=4afd6f55e2"></script>
which means that code which is meant to run in the context of the ServiceWorkerGlobalScope
(in which self.registration
is defined) is instead being run in the window
global scope, where self.registration
is undefined
. That is what's leading to the Cannot use 'in' operator to search for 'sync' in undefined
runtime error.
Just adjust your build to ensure that you don't end up with that <script>
tag executing your service worker code as part of your main app, and you should be fine.