mswjs / msw-storybook-addon

Mock API requests in Storybook with Mock Service Worker.
https://msw-sb.vercel.app
MIT License
410 stars 39 forks source link

Storybook may freeze when switching to a story that sends requests but does not define any routes. #25

Open cs-intellineers opened 3 years ago

cs-intellineers commented 3 years ago

We have a Storybook setup for a React app. Unfortunately the repository is private. I will try to create a repository that allows to recreate this issue that I'll describe below.

The packages and browsers we use: Package name Version
@storybook/react 6.2.8
msw 0.28.1
msw-storybook-addon 1.1.0
Browser Version
Chromium 90.0.4430.72 (Official Build) Arch Linux (64-bit)
Firefox 87.0 (64-bit)

We add the mswDecorator in the preview.js of Storybook like so:

import { addDecorator } from '@storybook/react'
import { initializeWorker, mswDecorator } from 'msw-storybook-addon'

initializeWorker()
addDecorator(mswDecorator)

Some of our stories define routes in parameters.msw, some do not. When Storybook is running (localhost:6006) it works fine initially and switching to other stories that do not send out any requests works also as expected.

However, we have one story that does sends numerous requests out to a local backend server. When loading Storybook with that story selected (e.g.: http://localhost:6006/?path=/story/problematic--story), it works also as expected. The problem arises when switching to the problematic story. It will freeze the browser completely. I wasn't able to get anything out of the chromium profiler as it never finishes to process the profile. Luckily I was able to get some hint from the Firefox profiler that it is stuck on a function called deferNetworkRequestsUntil.

The function the profiler refers to in source:

/**
 * Intercepts and defers any requests on the page
 * until the Service Worker instance is ready.
 * Must only be used in a browser.
 */
function deferNetworkRequestsUntil(predicatePromise) {
    // Defer any `XMLHttpRequest` requests until the Service Worker is ready.
    const originalXhrSend = window.XMLHttpRequest.prototype.send;
    window.XMLHttpRequest.prototype.send = function (...args) {
        // Keep this function synchronous to comply with `XMLHttpRequest.prototype.send`,
        // because that method is always synchronous.
        until$1(() => predicatePromise).then(() => {
            window.XMLHttpRequest.prototype.send = originalXhrSend;
            this.send(...args);
        });
    };
    // Defer any `fetch` requests until the Service Worker is ready.
    const originalFetch = window.fetch;
    window.fetch = (...args) => __awaiter(this, void 0, void 0, function* () {
        yield until$1(() => predicatePromise);
        window.fetch = originalFetch;
        return window.fetch(...args);
    });
}

I guess this is the one from msw: https://github.com/mswjs/msw/blob/2943c080bbdaaf74ec9e23147592fe76a0e6a147/src/utils/deferNetworkRequestsUntil.ts#L3-L29

Removing msw-storybook-addon an its setup from preview.js reliably removes the problem.

I realize what I am writing here is probably not much to go on. But maybe someone else encountered this before.

cs-intellineers commented 3 years ago

Also, removing addDecorator(mswDecorator) from the preview.js and applying the decorator only on stories that actually use mock routes does not change the outcome.

There is something with the service worker, that does not agree with our app. Unfortunately, I do not know enough about service workers in order to know how to break them or avoid doing so. Are there any common mistakes that are easily made in this regard?

kettanaito commented 3 years ago

Hey, @cs-intellineers. Thanks for reporting this.

Could you please try disabling the deferNetworkRequestsUntil by:

initializeWorker({ waitUntilReady: false })

Read more about waitUntilReady.

chornos13 commented 3 years ago

I have the same issue, has anyone found the work around ? besides disabling waitUntilReady ?

BrunoQuaresma commented 12 months ago

When I disable it, I start to get request errors.