msw icon indicating copy to clipboard operation
msw copied to clipboard

Chrome reloads infinitely when `serviceWorker.options.scope` is set

Open mizdra opened this issue 2 years ago • 10 comments

Prerequisites

Environment check

  • [X] I'm using the latest msw version
  • [X] I'm using Node.js version 14 or higher

Browsers

Chromium (Chrome, Brave, etc.)

Reproduction repository

https://github.com/mizdra/reproduction-msw-scope-bug

Reproduction steps

  1. npm i
  2. npm run dev
  3. Open http://localhost:5173/base with Google Chrome
    • I use Google Chrome 112.0.5615.137(Official Build) (arm64) on masOS Monterey 12.6.

Current behavior

Reloading the page many times at short intervals will cause it to enter an infinite reload loop.

https://github.com/mswjs/msw/assets/9639995/dab75c08-f022-4591-8b08-41e072ac37c1

Expected behavior

No infinite loops.

mizdra avatar May 25 '23 16:05 mizdra

If you interrupt the reload at the right time, you can take a peek at the code that requested the reload from the initiator tab.

https://github.com/mswjs/msw/assets/9639995/0b030ba5-7067-4074-bf2c-76ee16365f57

According to this, the following code appears to be causing infinite reloads:

  • https://github.com/mswjs/msw/blob/da92465b312b54a7a7e71168b1bdcb62daeef3b1/src/setupWorker/start/utils/getWorkerInstance.ts#L33

mizdra avatar May 25 '23 17:05 mizdra

In addition to Chrome, this problem was reproduced in Firefox. However, it did not reproduce in Safari.

mizdra avatar May 25 '23 17:05 mizdra

same problem for me any updated ?

MarwenIs avatar Jun 15 '23 13:06 MarwenIs

This problem does not yet seem to have been fixed.

FYI: You can temporarily work around this issue by installing ServiceWorker in the root path instead of using scope. This workaround only works for applications where it is not required to install under a subpath.

mizdra avatar Jun 18 '23 05:06 mizdra

Can confirm the same is happening for me.

  • MSW Worker file added to a static directory (non-root).
  • Path set via serviceWorker.url in .start(). No handlers set up at this stage.
  • Activating the worker using worker.start() will cause the site to reload indefinitely.
  • As above, looking at the Network Initiator tab identifies it as MSW causing the reload.

shapedigital avatar Jul 17 '23 10:07 shapedigital

This is my workaround which maybe useful for some cases.

For me, I got infinite reload when init mswjs outside of service worker scope.

let's say

  • mockServiceWorker.js is at /some-path/mockServiceWorker.js so service worker scope is /some-path/
  • Service worker url is configured to /some-path/mockServiceWorker.js
  • When try to init mswjs at /some-path, then cause infinite reload. (init at /some-path/ is working fine because it's in service worker scope)

workaround

  • Not init mswjs at path /some-path by checking current path
  • Cons is that you cannot stub request at /some-path page.
if (window.location.pathname.startsWith('/some-path/')) { // only init mswjs when path is in service worker scope
  const worker = setupWorker(...handlers);

  void worker.start({
    serviceWorker: {
      url: '/some-path/mockServiceWorker.js',
    }
  });
}

ptantanis avatar Nov 23 '23 03:11 ptantanis

This problem still exits in msw: 2.3.1 and I encountered it while setting up our nx monorepo of React/Vite apps.

Here is the workaround:

  • setup worker url (file path is apps/app1/public/mockServiceWorker.js)

apps/app1/src/App.tsx:

  worker.start({
    onUnhandledRequest: "bypass",
    serviceWorker: {
      url: "./mockServiceWorker.js",
    },
  })
  • create base url similarly to @ptantanis comment, note the 2 slashes:

apps/app1/vite.config.ts:

export default defineConfig({
  base: "/myBaseUrl/",
  server: {
    port: 1234
  }
  ...
}
  • access app at http://localhost:1234/myBaseUrl/

krzysztofradomski avatar Jul 31 '24 14:07 krzysztofradomski

This is my workaround which maybe useful for some cases.

For me, I got infinite reload when init mswjs outside of service worker scope.

let's say

  • mockServiceWorker.js is at /some-path/mockServiceWorker.js so service worker scope is /some-path/
  • Service worker url is configured to /some-path/mockServiceWorker.js
  • When try to init mswjs at /some-path, then cause infinite reload. (init at /some-path/ is working fine because it's in service worker scope)

workaround

  • Not init mswjs at path /some-path by checking current path
  • Cons is that you cannot stub request at /some-path page.
if (window.location.pathname.startsWith('/some-path/')) { // only init mswjs when path is in service worker scope
  const worker = setupWorker(...handlers);

  void worker.start({
    serviceWorker: {
      url: '/some-path/mockServiceWorker.js',
    }
  });
}

Thanks for the workaround! Alternatively, if you own your Web hosting server it is possible to "upgrade" SW scope by using Service-Worker-Allowed .ie including Service-Worker-Allowed: / in the worker file's response.

huygn avatar Aug 09 '24 09:08 huygn