Msw: Service worker slow / failing JS and image requests when running in cypress browser

Created on 28 Sep 2020  路  14Comments  路  Source: mswjs/msw

Describe the bug

When using MSW in my app and trying to run cypress, MSW cannot fetch images after the 1st run. I get:

mockServiceWorker.js:184 [MSW] Failed to mock a "GET" request to "http://localhost:3000/static/media/back-arrow.42b194d9.svg": TypeError: Failed to fetch
(anonymous) @ mockServiceWorker.js:184
Promise.then (async)
(anonymous) @ mockServiceWorker.js:183
mockServiceWorker.js:184 [MSW] Failed to mock a "GET" request to "http://localhost:3000/static/media/user-icon.f8b2f969.svg": TypeError: Failed to fetch
(anonymous) @ mockServiceWorker.js:184
Promise.then (async)
(anonymous) @ mockServiceWorker.js:183
mockServiceWorker.js:184 [MSW] Failed to mock a "GET" request to "http://localhost:3000/static/media/exclamation.bac54b11.svg": TypeError: Failed to fetch
(anonymous) @ mockServiceWorker.js:184
Promise.then (async)
(anonymous) @ mockServiceWorker.js:183
mockServiceWorker.js:184 [MSW] Failed to mock a "GET" request to "http://localhost:3000/static/media/scan-barcode.2264fdba.svg": TypeError: Failed to fetch

Cypress then gets into the loop of trying to request it, failing and trying to request it again resulting in crawling of a page load.

It seems like the service worker is sometimes finding the images and sometimes not:

Request URL: http://localhost:3000/static/media/back-arrow.42b194d9.svg
Request Method: GET
Status Code: 200 OK (from ServiceWorker)

Some JS also takes over 15s to load in the cypress browser.
Screenshot 2020-09-28 at 17 29 11

Am I missing something or is anything else required to allow cypress to use mocks? Without msw cypress works completely fine and never takes long to load any JS files.

Environment

  • msw: 0.21.2
  • nodejs: 10.16.3
  • npm: 6.90
  • Cypress 5.1.0

Please also provide your browser version.
Chrome Latest Stable

To Reproduce

Steps to reproduce the behavior:

  1. Mock requests in your application. (npm start runs with all mocks by default), so mocking is in my application.
  2. Run first set of cypress test (via cypress ui), rerun the same tests without closing the window and you will see the error.

Expected behavior

A clear and concise description of what you expected to happen.
Loading of files (js, images etc) should load quickly not over 15s, images requests should also be quick

rest bug browser

Most helpful comment

@marcosvega91 Sorry it took so long but I did my best to create a reproduction repo on a smaller scale (our app where I saw this is much bigger and has code-splitting etc but I think I was able to successfully reproduce it.)

See https://github.com/jaslloyd/msw-sw-bug,

I left instructions in the readme, you will see it's making over 1400+ requests when there is a test failure which is pretty much what was happening in our other app but on a bigger scale. Comparatively, when you remove MSW it makes 12 requests. You can imagine when these contain big enough JS bundles the page load can be significant as seen in my image.

Let me know if you need anything else

All 14 comments

Hi @jaslloyd thanks for raising this :).

Do you have a reproduction repo? I can take a look and understand better the issue 馃殌

@marcosvega91 Sorry it took so long but I did my best to create a reproduction repo on a smaller scale (our app where I saw this is much bigger and has code-splitting etc but I think I was able to successfully reproduce it.)

See https://github.com/jaslloyd/msw-sw-bug,

I left instructions in the readme, you will see it's making over 1400+ requests when there is a test failure which is pretty much what was happening in our other app but on a bigger scale. Comparatively, when you remove MSW it makes 12 requests. You can imagine when these contain big enough JS bundles the page load can be significant as seen in my image.

Let me know if you need anything else

Hi @jaslloyd I'll try to understand what is happening under the hood. Thanks for the repo ! 馃挴

The problem seams a Cypress issue coming from version 4.0.0 .
I have tried to disable worker from dev tools, remove MSW and remove worker but the issue still appear.. I think that we can open an issue there. What do you think @jaslloyd ?

I have found this issue on cypress https://github.com/cypress-io/cypress/issues/8491

@marcosvega91 So I agree there is something with cypress but is it only cypress? As i said in that repo if you remove msw it only makes 12 requests (that is still a lot for a small app) but when you add back in MSW it makes over 1400 requests.

I agree cypress is making way more requests than it should but when you put a msw service worker on top of that it explodes the requests.

The issue doesn't appear for me, you need to make sure you completely close out cypress and rebook it. I will attach screenshots of this bug happening with MSW enabled vs disabled

With MSW enabled:
Screenshot 2020-10-05 at 17 37 14

Disabled MSW / Cleared console / Unregistered SW:
Screenshot 2020-10-05 at 17 37 59

1314 vs 11 Requests only difference between two runs in MSW is enabled on first

I don't have SW registered as for the screen
image
I have uninstalled MSW and removed the service worker from public folder and I have a lot of failed requests
image
wired 馃 . I have changed the image to try with more then svg images

@marcosvega91 That is super weird...so I just tried it again and i got your result what the hell is going on lol. Let me send this repo on that cypress issue maybe its something they can spot with MSW disabled

Unfortunately I'm not really expert with Cypress, but I confirm that is really strange. Maybe the internal proxy of cypress is buggy

Hey, @jaslloyd. Thanks for raising this. Without doubt integration with Cypress is quite difficult and we're glad that you're sharing this with us so we can improve it.

Worker registration / client activation race

First things first, let's figure out why sometimes the worker serves the image (assets) and sometimes not. That's an expected behavior and it's caused by how mocking is handled in the worker internally. I'll try to explain it briefly below.

Whenever the worker is registered it checks if the client has been activated (signals a message in a MessageChannel). This means that a certain client (tab) is ready to accept mocked responses. While there are no clients the worker bypasses all requests. When this happens your assets are requested as-is (no worker cog icon next to them). When the client is activated, the worker keeps its ID and then each request, including static assets, gets signaled to the msw library to check if it should be mocked. Since you don't have a request handler for a static asset, the library sends MOCK_NOT_FOUND message to the worker, and the worker fetches that assets as-is (bypassing). Whenever you fetch something from within a worker it creates _a new XHR request_, which also has the worker cog icon next to it.

Both client activation and worker registration are asynchronous actions. This subjects them to race conditions, making a client ready at a different time frame. Thus, sometimes you see a static asset fetched as-is, and sometimes with the worker cog icon. Again, that is a perfectly fine behavior and it shouldn't raise any issues. I doubt that we should be looking into this behavior as the reason for the issue, it must be elsewhere.

Back to the issue

I don't have anything to suggest right now, as I need to look into the reproduction repo (huge thanks for preparing it!) and investigate the issue there. Please share your own findings with us so we are more efficient in solving this. Thanks.

I also took a look and I noticed that there are 2 clients that are registered (a top-level client, and a nested client). The nested is included in the clients object, while the top-level one isn't.

I wonder if this could be the culprit of the amount of requests that are visible in the network tab.
I thought if we would add an early return inside the fetch method, before invoking event.respondWith, that it would resolve these issues.

+  if (!clients[clientId]) {
+    return;
+  }

But it does not, and I don't know why...
For example, if we take a look at the repo and add this check, the amount of requests is lowered by 200, but it's still the double in comparison to without using MSW.

Can you please try to reproduce this issue with the latest release of msw?

We've improved how requests are handled in the fetch event of the worker (as @timdeschryver suggested above), which may have a performance impact on this scenario. Please let us know.

I'm closing this due to inactivity.

The latest release of msw brings an improvement to how bypassed requests are handled (no request context created, the request is completely bypassed). I believe that should contribute greatly to fixing this issue.

Was this page helpful?
0 / 5 - 0 ratings