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.

Chrome Dev tools XHR

See original GitHub issue

Describe the bug

Not sure if it is even a msw problem, but maybe someone knows the answer. For some reason, when msw is enabled, I can not set up a filter to see only XHR requests in Chrome network tab. See how it looks like below (note, that static files are displayed even though the XHR filter is on.)

Environment

  • msw: 0.21.2
  • nodejs: 12.16.1
  • npm: 6.14.8
  • Chrome Version 85.0.4183.121 (Official Build) (64-bit)

To Reproduce

Steps to reproduce the behavior:

  1. Set up msw for browser as described in official docs
  2. Open Chrome Dev Tools
  3. Turn on filter XHR
  4. Reload the page.
  5. You will see all requests.

Expected behavior

Only XHR requests are displayed

Screenshots

Screenshot 2020-10-02 at 15 33 02

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:11 (7 by maintainers)

github_iconTop GitHub Comments

2reactions
kettanaitocommented, Oct 8, 2020

During the work on this I’ve found out a few details that I’d like to share.

Short answer

No, this won’t be possible to do due to the Service Worker specification.

Long answer

The worker’s “fetch” event triggers for any HTTP request from the client once the worker is active. The fetch event handler is a synchronous function, which may call event.respondWith() to respond with any Response, but it must call it synchronously:

self.addEventListener('fetch', function (event) {
  event.respondWith(anyPromise) // OK
  
  await somePromise()
  event.respondWith(...) // INVALID STATE
})

So there’s the first behavior we learn:

  • event.respondWith() must be called synchronously in the “fetch” event handler.

To fetch data in this worker’s event handler you can use the fetch() API. Since it’s async, we can only use it within the respondWith() Promise:

event.respondWith(async () => {
  return fetch('...').then(data => data.json())
})

Whenever you perform a fetch() call within the worker’s scope it gets registered as the XHR in the Network tab. That is the behavior one cannot change. Thus, the next discovery:

  • fetch() calls in the worker’s scope are always registered as XHR

Now let’s analyze what happens to a request. Specifically, to a static asset request that shouldn’t be mocked. Here’s the journey it undergoes:

  1. Client loads its JavaScript code.
  2. The JS code registers the worker.
  3. The JS code performs an HTTP request.
  4. Request is caught by the “fetch” event of the worker.
  5. Worker signals to MSW to see if this request should be mocked (async action).
  6. If not, it performs request as is via event.respondWith(fetch(event.request)).

Since the step 5 is async, it must be nested in the event.respondWith() promise. If the request shouldn’t be mocked, to perform an original request one needs to call fetch(event.request), which always produces an XHR request. This means that the requests that should be bypassed are performed as XHR and you can see them twice in your browser’s Network tab.

There are much more nuances to the async worker behavior. For instance, there is a time window between steps 2 and 3 and if a request happens there it’s always bypassed, as that means “the worker is not ready to signal to MSW”. Those requests will not be listed as XHR, because the fetch event handler short circuits on those requests outside of the event.respondWith() function call.

If this request duplication in the Network is confusing, this is how you can think of it:

  1. First (non XHR) request is what your app makes.
  2. Second (XHR) request is what the worker makes in order to fetch the original (bypassed) respond data and use it to respond to your first request.
1reaction
kettanaitocommented, Oct 9, 2020

I’m closing the issue because there isn’t much we can do on this behavior. The PR that slightly improves the requests bypassing will land in the next minor version. Thanks for raising this!

Read more comments on GitHub >

github_iconTop Results From Across the Web

What does "XHR Load" mean in Chrome Developer Tools?
2. "XHR" is just a technical name for what people call an "Ajax request". This shows the loading time of the request, that...
Read more >
XHR Breakpoints | Down and Dirty with Chrome Developer ...
A deep dive into advanced functionality within the Chrome Developer tools that will enable you to more effectively build and debug web apps....
Read more >
Network features reference - Chrome Developers
A comprehensive reference of Chrome DevTools Network panel ... To replay an XHR request, do one of the following in the Requests table:....
Read more >
How to inspect AJAX requests with Chrome tools
When the developer tools console opens, click on the Network tab, then click XHR below. 5. You can now see the AJAX requests....
Read more >
How to replay XHR request - Google Groups
to Google Chrome Developer Tools. How can i replay an XHR request ? in firebug i just can the request in a new...
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