question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Non-CORS requests from DevTools can pollute the cache

See original GitHub issue

Library Affected: workbox v5.1.3 npm

Browser & Platform: Google Chrome v85

Issue or Feature Request Description: CORS requests from known CDNs like “fonts.googleapis.com” o “cdn.jsdelivr.net” often fail, but are cached correctly as cors.
On Chrome the errors can be triggered by toggling the development panel and reloading the page. But can happen for other unknown reasons too. On Firefox the issue still occurs, in different conditions, and can even affect the page’s look (when “normalize.css” goes missing for example)
It happens on different machines under different networks.

I’ve made a minimal reproducible example, you can try it on pages. Open the console and see.

Recap of what said here:


  • observation 1: when reloading the page, only three requests are logged: for the stylesheet, the main js file, and the favicon.
    No html file. Is this expected? I thought the http cache affected workbox’s fetches, not the entire event capturing.

  • observation 2:
    after the developer tools have been opened (Ctrl+shift+i):

    • the first page reload will trigger all the requests again, and the cors error will always occur.
    • the second page reload will trigger all the requests again, no error messages will be print.
    • the subsequent page reloads will show the same three requests mentioned above

    after the developer tools have been closed:

    • the first page reload will trigger all the requests again, no error messages will be print.
    • the subsequent page reloads will show the same three requests mentioned above

Looks like opening the dev tools alters some caching mechanism. It temporarily breaks cors requests too. Not sure why the error persisted between reloads in my previous tests, might have been because I was toggling the dev panel.


I’ve ran the app in Firefox, to see if I could gather something more. It says:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://cdn.jsdelivr.net/npm/normalize.css@8/normalize.min.css. (Reason: CORS request did not succeed).

GET https://cdn.jsdelivr.net/npm/normalize.css@8/normalize.min.css

Failed to load ‘https://cdn.jsdelivr.net/npm/normalize.css@8/normalize.min.css’. A ServiceWorker passed an opaque Response to FetchEvent.respondWith() while handling a ‘cors’ FetchEvent. Opaque Response objects are only valid when the RequestMode is ‘no-cors’. sw.js:1853:26

GET https://fonts.googleapis.com/css2?family=Open+Sans&display=block

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://fonts.googleapis.com/css2?family=Open+Sans&display=block. (Reason: CORS request did not succeed).

Failed to load ‘https://fonts.googleapis.com/css2?family=Open+Sans&display=block’. A ServiceWorker passed an opaque Response to FetchEvent.respondWith() while handling a ‘cors’ FetchEvent. Opaque Response objects are only valid when the RequestMode is ‘no-cors’.

A Learn More link sends here, where it talks about general network/http errors, but I don’t think that’s the case. Neither are adblockers, because chrome with external debugger starts blank, and my “Firefox Developer Edition” installation is blank.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:16 (7 by maintainers)

github_iconTop GitHub Comments

2reactions
jeffposnickcommented, Sep 17, 2020

@wanderview was good enough to jump in with some debugging help, and figured out what’s going on.

The DevTools interface basically behaves like another client of the service worker, and in order to populate its user interface with details about the various resources being loaded, makes its own requests for each URL. When those requests are for cross-origin URLs, they’re made without CORS. Those non-CORS requests made by DevTools do trigger the service worker’s fetch handler, and the revalidation step in the Workbox strategy you’re using ends up using a non-CORS (opaque) response to populate the cache.

That explains why opening DevTools triggers this behavior. The fact that you explicitly require a CORS response (due to the crossorigin="anonymous" attribute on your DOM elements) explains why you experience a complete failure to load the subresources.

So… that’s a summary of what’s going on.

You can explicitly work around it in your specific use case by adding an instance of the CacheableResponsePlugin that requires a 200 response status to your strategy:

import {CacheableResponsePlugin} from 'workbox-cacheable-response';
import {StaleWhileRevalidate} from 'workbox-strategies';

new StaleWhileRevalidate({
  cacheName: 'cdn',
  plugins: [
    new CacheableResponsePlugin({statuses: [200]}),
  ],
});

The documentation for workbox-cacheable-response includes an explanation of its usage and why some strategies default to caching opaque responses.

Beyond resolving your specific issue, there are a couple of longer-term ways of following-up:

  1. Do nothing. Given that this happens due to interaction with DevTools, it’s not likely to affect production users, but it can obviously cause frustration for developers if they frequently open DevTools and have subresources which require CORS responses and use a stale-while-revalidate or network-first strategy.

  2. Change workbox-routing so that it explicitly detects requests that originate from DevTools (I’m assuming there’s a programmatic way of doing that via some header…) and ensure that Workbox doesn’t respond to those fetch events.

  3. Change the StaleWhileRevalidate and NetworkFirst strategies to detect what the currently cached responses’s type is, and if it’s not 'opaque', refuse to overwrite it with an 'opaque' response.

  4. Change the StaleWhileRevalidate and NetworkFirst strategies to detect what the currently cached responses’s type is, and if it’s not 'opaque', refuse to overwrite it with an 'opaque' response. Instead, perform an additional fetch() with an explicit 'cors' mode and revalidate the cache with that response instead.

My personal preference is probably 2., but Ben points out that if Workbox refused to respond to DevTool’s requests, the DevTools interface may end up showing a different response that what the web page sees. You could imagine, for instance, a Workbox route that created a synthetic response by stitching together multiple partial sources. That synthetic response would not be visible to DevTools. So I’m not really sure what to do about that.

Option 3. might be the best compromise, but it does add in some extra overhead, and in the back of my head, I wonder whether there are any legitimate use cases that it would end up breaking.

For the meantime, it’s option 1. by default.

1reaction
jeffposnickcommented, Dec 3, 2020

It seems like there’s some movement on the underlying issue at https://bugs.chromium.org/p/chromium/issues/detail?id=1092637, so I’m going to defer to the DevTools team to find a permanent resolution, as opposed to trying to address this in Workbox.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Service worker ignores the fetch cache setting - Stack Overflow
From the MDN docs: no-store — The browser fetches the resource from the remote server without first looking in the cache, and will...
Read more >
Network features reference - Chrome Developers
A comprehensive reference of Chrome DevTools Network panel ... In this case, you can disable caching to see the full request headers.
Read more >
Cache pollution - Wikipedia
Cache pollution describes situations where an executing computer program loads data into CPU cache unnecessarily, thus causing other useful data to be ...
Read more >
Disable Caching During Development with Browser Tools
Once the developer tools are open, there is a set of tabs along the top. Select network. Disable cache option in chrome devtools....
Read more >
DevTools Overview - Angular
Angular DevTools is a browser extension that provides debugging and ... You can find Angular DevTools in the Chrome Web Store and in...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found