Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot load the application if the browser doesn't have slash at the end of the URL #2047

Closed
4 tasks done
nemonemi opened this issue Feb 20, 2024 · 1 comment
Closed
4 tasks done
Labels
bug Something isn't working needs:triage Issues that have not been investigated yet. scope:browser Related to MSW running in a browser

Comments

@nemonemi
Copy link

nemonemi commented Feb 20, 2024

Prerequisites

Environment check

  • I'm using the latest msw version
  • I'm using Node.js version 18 or higher

Browsers

Chromium (Chrome, Brave, etc.)

Reproduction repository

No repo

Reproduction steps

...

Current behavior

My application has a base path configured in the Vite config and the React router.

I've configured MSW to be loaded from the relative path.

export async function enableMocking() {
  const worker = setupWorker(...handlers);

  return await worker.start({
    serviceWorker: {
      url: 'mockServiceWorker.js',
    },
    onUnhandledRequest: 'bypass',
  });
}

The file gets loaded
image

But the screen doesn't, and it throws this in the console:
image

Error: [MSW] Failed to locate the Service Worker registration.

This most likely means that the worker script URL "mockServiceWorker.js" cannot resolve against the actual public hostname (localhost:4200). This may happen if your application runs behind a proxy, or has a dynamic hostname.

Please consider using a custom "serviceWorker.url" option to point to the actual worker script location, or a custom "findWorker" option to resolve the Service Worker registration manually. More details:  at startWorkerInstance ... etc.
  | startWorkerInstance | @ | msw_browser.js?v=3c07e0f6:1097
-- | -- | -- | --
  | Promise.then (async) |   |  
  | (anonymous) | @ | main.tsx:37
  | Show less

</span></div>

However, if I would to add the / at the end of the URL, then everything works as expected.

If I set the base path in the MSW config, then I get an infinite screen reload for the URL without the \, but works for the URLs with it.

worker.start({
    serviceWorker: {
      url: '/supplier-management/lifecycle/approved-suppliers/mockServiceWorker.js',
    },
    onUnhandledRequest: 'bypass',
  });

Why would the loading of the resource depend on the slash in the URL?

Expected behavior

The URL without the slash at the end should load normally with mockServiceWorker properly setup.

@nemonemi nemonemi added bug Something isn't working needs:triage Issues that have not been investigated yet. scope:browser Related to MSW running in a browser labels Feb 20, 2024
@kettanaito
Copy link
Member

Hi.

Why would the loading of the resource depend on the slash in the URL?

Because the way URLs on the web get resolved depends on the trailing slash:

new URL('mockServiceWorker.js', 'https://example.com/deeply/nested/path').href
// 'https://example.com/deeply/nested/mockServiceWorker.js'

new URL('mockServiceWorker.js', 'https://example.com/deeply/nested/path/').href
// 'https://example.com/deeply/nested/path/mockServiceWorker.js'

new URL('./mockServiceWorker.js', 'https://example.com/deeply/nested/path').href
// 'https://example.com/deeply/nested/mockServiceWorker.js'

new URL('./mockServiceWorker.js', 'https://example.com/deeply/nested/path/').href
// 'https://example.com/deeply/nested/path/mockServiceWorker.js'

Notice how different resource URLs are produced depending on the presence of a trailing slash in the base URL as well as how you format the pathname.

Yours is the very first example from above. It doesn't result in the URL you expect, and that's per web standards. You have to provide the correct worker script URL for MSW to fetch and register it.

How to solve this

(Recommended) Serve the worker script from the root

If you can, serve /mockServiceWorker.js from the root of your website: http://localhost:4200/mockServiceWorker.js. This will allow you to control the network across the entire app, and rid you of having to deal with constructing a proper worker script URL.

(Recommended) Provide an absolute URL including your base path

When using a custom base path in your app, you have to include it in the serviceWorker.url option to worker.start() as well. This is a great way for you to be explicit where the worker script is located without having to change the actual base path (e.g. by adding a trailing slash to it for every consumer).

worker.start({
  serviceWorker: {
    url: new URL('mockServiceWorker.js', BASE_PATH + '/').href
  }
})

Add trailing slash to base URL

Adding a trailing slash to your base URL will resolve the path to the worker script correctly:

new URL('mockServiceWorker.js', 'http://localhost:4200/supplier-management/lifecycle/approved-suppliers/').href
// 'http://localhost:4200/supplier-management/lifecycle/approved-suppliers/mockServiceWorker.js'

@github-actions github-actions bot locked and limited conversation to collaborators Oct 29, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working needs:triage Issues that have not been investigated yet. scope:browser Related to MSW running in a browser
Projects
None yet
Development

No branches or pull requests

2 participants