Recently the react-dev-utils that is part of the react-scripts package used by create react app got an update that makes it so that the public path is used in the dev-server. The mockedServiceWorker will need to be registered with this public url but now it will not intercept any requests.
msw: 0.20.5create-react-app: 3.4.1Please also provide your browser version.
chrome 84
Steps to reproduce the behavior:
//src/mocks/handlers.ts
import { rest } from "msw";
const handlers = [
rest.get(`${process.env.PUBLIC_URL}/test`, (req, res, ctx) =>
res(ctx.json({ message: "Handled by mock service worker" }))
),
];
export { handlers };
//src/mocks/browser.ts
import { setupWorker } from 'msw'
import { handlers } from './handlers'
export const worker = setupWorker(...handlers);
Remember to add the process.env.PUBLIC_URL to the path of the service worker
//index.tsx
import("./mocks/browser").then(({ worker }) => {
worker
?.start({
serviceWorker: {
url: `${process.env.PUBLIC_URL}/mockServiceWorker.js`,
},
})
.then(() => {
ReactDOM.render(
<React.StrictMode>
<button
onClick={() =>
fetch(`${process.env.PUBLIC_URL}/test`)
.then((response) => response.json())
.then((json) => console.log("Got reponse:", json.message))
.catch(error => console.error(error))
}
>
FETCH
</button>
</React.StrictMode>,
document.getElementById("root")
);
});
});
I would expect to be able to run the application with a PUBLIC_URL and still use MSW
Hello! I looked into this for you. Good and bad news - the only way you're going to be able to make this work is by making sure you have a trailing slash on your URL - http://localhost:3000/foo/bar/.
Basically, msw is working fine, but it's the actual claim behavior of service workers in general that is a problem. Here is an example error of when I tried to force scope: '/':
The path of the provided scope ('/') is not under the max scope allowed ('/foo/bar/'). Adjust the scope, move the Service Worker script, or use the Service-Worker-Allowed HTTP header to allow the scope.
Notice it automatically enforcing the trailing slash. There is a lengthy thread about the problematic behavior here: https://github.com/w3c/ServiceWorker/issues/1272.
I don't exactly understand your explanation for needing to have the app loaded from a sub route, but the best idea is to just have the mockServiceWorker.js file served from the root of the domain so it has access to all child routes if possible. If not, the trailing slash appears to be the only resolution.
Thanks. Your explanation of the service worker scope was really helpful. I鈥檒l close the ticket.
I was having the same issue. Here is my solution, I have a quick redirect when running mocked version.
// index.tsx
async function render() {
if (process.env.REACT_APP_MOCKED_DATA === "true") {
if (window.location.pathname === "/abc") {
window.location.pathname = "/abc/";
return;
}
// eslint-disable-next-line
const { worker } = require("./mock-api/browser");
await worker.start({
waitUntilReady: true,
serviceWorker: {
url: `${process.env.PUBLIC_URL}/mockServiceWorker.js`,
},
onUnhandledRequest: (req: MockedRequest) => {
console.error("Found an unhanded %s request to %s", req.method, req.url.href);
},
});
}
ReactDOM.render(<App />, document.getElementById("root"));
}
render();
This might have some unintended consequences as locally there will be a trialing slash.
Most helpful comment
I was having the same issue. Here is my solution, I have a quick redirect when running mocked version.
// index.tsx
This might have some unintended consequences as locally there will be a trialing slash.