Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prod error: Unable to import module 'workbox-google-analytics' #1186

Closed
NoamPaz opened this issue Jan 18, 2018 · 13 comments
Closed

Prod error: Unable to import module 'workbox-google-analytics' #1186

NoamPaz opened this issue Jan 18, 2018 · 13 comments
Assignees
Labels
Bug An issue with our existing, production codebase. workbox-google-analytics

Comments

@NoamPaz
Copy link

NoamPaz commented Jan 18, 2018

Library Affected:
3.0.0-alpha.5

Browser & Platform:
Version 63.0.3239.108 (Official Build) (64-bit) - PC

Issue Description:
Use workbox google analytics:

workbox.googleAnalytics.initialize();

On dev mode it works, but when I'm switching it to production mode:

workbox.setConfig({ debug: false });

I get the following error:

workbox-sw.js:formatted:57 Unable to import module 'workbox-google-analytics' from 'https://storage.googleapis.com/workbox-cdn/releases/3.0.0-alpha.5/workbox-google-analytics.prod.js'.
loadModule @ workbox-sw.js:formatted:57
get @ workbox-sw.js:formatted:34
(anonymous) @ workboxServiceWorker.js:60

Uncaught SyntaxError: Unexpected token new
    at Object.loadModule (workbox-sw.js:formatted:54)
    at Object.get (workbox-sw.js:formatted:34)
    at workboxServiceWorker.js:60

Additional info:
workboxServiceWorker.js line 60 is the line of workbox.googleAnalytics.initialize(); command in my service worker.

@jeffposnick
Copy link
Contributor

I'm able to reproduce this locally with a sw.js consisting of:

importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.0.0-alpha.5/workbox-sw.js');

workbox.setConfig({ debug: false });
workbox.googleAnalytics.initialize();

After unwinding the minification a bit to figure out which statement is actually causing the syntax error, it looks like it's the new Promise(...) from

const e = yield c = o.body, new Promise((e, t) => {
  const n = new FileReader;
  n.onloadend = (() => e(n.result)), n.onerror = (() => t(n.error)), n.readAsText(c)
});

The corresponds to the following two blocks of unminified code:

const getTextFromBlob = (blob) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = () => reject(reader.error);
reader.readAsText(blob);
});
};

const payload = await getTextFromBlob(requestInit.body);

It seems like the process of running this code through the async-to-generator transpilation followed by UglifyJS minification has led to minified code that contains a syntax error.

@philipwalton, do you have some bandwidth to investigate why that usage in the original source might be minified incorrectly, and potentially rewrite the code to avoid using async/await for that particular snippet if there's no other way of working around it?

(There are no in-browser integration tests for workbox-google-analytics, which would have caught this.)

@jeffposnick jeffposnick added Bug An issue with our existing, production codebase. workbox-google-analytics labels Jan 18, 2018
@gauntface
Copy link

@philipwalton if you don't have bandwidth for this - please let me know I'll pick it up.

@philipwalton
Copy link
Member

@gauntface if you have time, that would be great. I'm trying to get two other projects out the door before the M64 release.

@jeffposnick
Copy link
Contributor

I'm happy to pick up the fix, too 😄 I just figured I'd give Phil first crack at it.

Testing things out locally, it looks like explicitly flagging getTextFromBlob as being an async function and awaiting the new promise inside of the function is enough to get the final prod bundle happy.

(Thanks for filing #1193 to track the integration test, Matt.)

@dumbmatter
Copy link

I'm still seeing this issue with Workbox 3.5.0 in Firefox 62 but not in Chrome 69. You can see this at https://beta.basketball-gm.com/

Unable to import module 'workbox-google-analytics' from 'https://storage.googleapis.com/workbox-cdn/releases/3.5.0/workbox-google-analytics.prod.js'. workbox-sw.js:1:1170
loadModule
https://storage.googleapis.com/workbox-cdn/releases/3.5.0/workbox-sw.js:1:1170
get
https://storage.googleapis.com/workbox-cdn/releases/3.5.0/workbox-sw.js:1:755
<anonymous>
https://beta.basketball-gm.com/sw.js:1:2772
NetworkError: Failed to load worker script at https://storage.googleapis.com/workbox-cdn/releases/3.5.0/workbox-google-analytics.prod.js (nsresult = 0x80004004) workbox-sw.js:1
TypeError: ServiceWorker script at https://beta.basketball-gm.com/sw.js for scope https://beta.basketball-gm.com/ encountered an error during installation.

@philipwalton
Copy link
Member

Hmmm, @dumbmatter I'm not seeing that error when I run your site in FF 62.0 on Mac OS 10.13.6. What system are you running it on?

@jeffposnick jeffposnick reopened this Sep 17, 2018
@dumbmatter
Copy link

I use Ubuntu, here is a screenshot of what I see:

image

I have a Browserstack account so I tried Firefox 62 on Mac High Sierra and Windows 10, and everything worked fine there. How strange!

Here is the contents of https://storage.googleapis.com/workbox-cdn/releases/3.5.0/workbox-google-analytics.prod.js when I load that directly in Firefox:

this.workbox=this.workbox||{},this.workbox.googleAnalytics=function(e,n,t,o,r,c,s){"use strict";try{self.workbox.v["workbox:google-analytics:3.5.0"]=1}catch(e){}const l=/^\/(\w+\/)?collect/,i=(a=babelHelpers.asyncToGenerator(function*(e){return yield new Promise(function(n,t){const o=new FileReader;o.onloadend=function(){return n(o.result)},o.onerror=function(){return t(o.error)},o.readAsText(e)})}),function(e){return a.apply(this,arguments)});var a;const w=e=>(u=babelHelpers.asyncToGenerator(function*(n){let t,{url:o,requestInit:r,timestamp:c}=n;if(o=new URL(o),r.body){const e=r.body instanceof Blob?yield i(r.body):r.body;t=new URLSearchParams(e)}else t=o.searchParams;const s=c-(Number(t.get("qt"))||0),l=Date.now()-s;if(t.set("qt",l),e.parameterOverrides)for(const n of Object.keys(e.parameterOverrides)){const o=e.parameterOverrides[n];t.set(n,o)}"function"==typeof e.hitFilter&&e.hitFilter.call(null,t),r.body=t.toString(),r.method="POST",r.mode="cors",r.credentials="omit",r.headers={"Content-Type":"text/plain"},n.url=`${o.origin}${o.pathname}`}),function(e){return u.apply(this,arguments)});var u;return e.initialize=((e={})=>{const i=t.cacheNames.getGoogleAnalyticsName(e.cacheName),a=new n.Plugin("workbox-google-analytics",{maxRetentionTime:2880,callbacks:{requestWillReplay:w(e)}}),u=[(e=>{const n=new c.NetworkFirst({cacheName:e});return new o.Route(({url:e})=>"www.google-analytics.com"===e.hostname&&"/analytics.js"===e.pathname,n,"GET")})(i),(e=>{const n=new c.NetworkFirst({cacheName:e});return new o.Route(({url:e})=>"www.googletagmanager.com"===e.hostname&&"/gtag/js"===e.pathname,n,"GET")})(i),...(e=>{const n=({url:e})=>"www.google-analytics.com"===e.hostname&&l.test(e.pathname),t=new s.NetworkOnly({plugins:[e]});return[new o.Route(n,t,"GET"),new o.Route(n,t,"POST")]})(a)],f=new r.Router;for(const e of u)f.registerRoute(e);self.addEventListener("fetch",e=>{const n=f.handleRequest(e);n&&e.respondWith(n)})}),e}({},workbox.backgroundSync,workbox.core._private,workbox.routing,workbox.routing,workbox.strategies,workbox.strategies);

//# sourceMappingURL=workbox-google-analytics.prod.js.map

@dumbmatter
Copy link

Okay after writing that I realized I'm being stupid - it's being blocked by my ad blocker (uBlock Origin).

However, it is not a great for Workbox if the default behavior of a very common ad blocker is to completely block all service workers using this feature, rather than simply blocking Google Analytics tracking.

@philipwalton
Copy link
Member

Hmmm, seems like it's worth filing a bug with uBlock Origin.

I agree it's not great for Workbox, but at this point we can't just change the name of our module (presumably uBlock Origin is just blocking anything with the name "analytics" in it?), so it seems like the best thing to do is for uBlock users to complain about the behavior.

@dumbmatter
Copy link

That's probably true, but it's fighting an uphill battle to try to prevent every ad blocker from ever blocking it. Is there any way to try/catch the import of workbox-google-analytics.prod.js, so you could still load the service worker even if some HTTP request failed? Or would that cause more problems, by leaving some users with an incomplete service worker in perpetuity?

All this makes me wonder if I would be better off just bundling Workbox into my sw.js file, to prevent any issue like this in the future. That's what I do for all my JS dependencies outside the service worker.

@philipwalton
Copy link
Member

Is there any way to try/catch the import of workbox-google-analytics.prod.js, so you could still load the service worker even if some HTTP request failed?

We could try/catch the import, but then your code would still error as soon as you referenced workbox.googleAnalytics.initialize().

We could go even a step further and add a proxy to the namespace if the import failed. That might work in the Google Analytics case, but it wouldn't work in the general case.

@jeffposnick do you have any thoughts here as to whether it's worth special casing the Google Analytics importScripts call to avoid errors that break your entire service worker?

All this makes me wonder if I would be better off just bundling Workbox into my sw.js file, to prevent any issue like this in the future. That's what I do for all my JS dependencies outside the service worker.

So, this is exactly what I do for my personal website. I reference all the workbox modules using ES module import syntax and then bundle it with Rollup. Here's an example on a development branch:
https://github.com/philipwalton/blog/blob/9b29417/assets/sw/sw.js

@jeffposnick
Copy link
Contributor

Hmm, that's tricky. I don't know how we could cleanly handle this given the complications mentioned above—the workarounds are not great.

What if we just renamed the workbox-google-analytics.prod.js script as part of the v4 release when we have the chance to make some breaking changes?

@philipwalton
Copy link
Member

We could try renaming the script (assuming that works). I'm not crazy about it, but it's probably worth avoiding issues like this if we can.

I'm moving this to #1646 to track it separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug An issue with our existing, production codebase. workbox-google-analytics
Projects
None yet
Development

No branches or pull requests

5 participants