examples
examples copied to clipboard
add next.js app router example
Adds a Next.js 14 (App directory ) + MSW usage example.
Todos
- [x] https://github.com/vercel/next.js/pull/68193
- [ ] https://github.com/vercel/next.js/issues/69098
Server-side integration
I got the server-side MSW integration working in Next.js by using the instrumentation hook:
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
const { server } = await import('./mocks/node')
server.listen()
}
}
This allows MSW to intercept server-side requests Next.js makes.
Downsides
- Next seems to evaluate the instrumentation hook once. The import graph it creates will not update if you change
mocks/handlers.tsbecause nothing but the instrumentation hook depends on that import. This means stale mocks until you re-run Next.js/force it re-evaluate the instrumentation hook.
I'm our company we are using this example as a reference.
@SalahAdDin
I'm our company we are using this example as a reference.
is it working? I've tried to use, but it's showing these messages below:
Internal error: TypeError: fetch failed
`[MSW] Warning: intercepted a request without a matching request handler:
• POST https://telemetry.nextjs.org/api/v1/record`
@SalahAdDin
I'm our company we are using this example as a reference.
Is it working? I've tried to use it, but it's showing these messages below:
Internal error: TypeError: fetch failed`[MSW] Warning: intercepted a request without a matching request handler:
Not checked it yet, We just set it up.
@kettanaito I don't know why but MSW is not intercepting page request. The mock is enabled but does not catch any fetch.
how does playwright work with this? My test makes the actual api call instead of the mocked call
@pandeymangg, there should be nothing specific to Playwright here. You enable MSW in your Next.js app, then navigate to it in a Playwright test and perform the actions you need.
Hey @kettanaito what is the status of this example? 😄
Got some of this working in my own app, but curious to see the libraries official recommended approach. Thanks 🙏
PS. love the library, it rivals trpc and react query as my favourite open source projects.
@pandeymangg, the Playwright integration is the same as in this example:
- Enable MSW client-side.
- Run your app.
- Navigate to it in Playwright.
There has never been anything specific to Cypress/Playwright that MSW required.
@mw999, that is a high praise, thank you! No updates on this example, I didn't have time to look into it and, frankly, very little I can do here. If Next.js doesn't pick up changes from the instrumentation hook in HRM, I cannot fix that. I won't be recommending half-baked experiences. For now, you cannot officially use MSW in Next.js.
This is great work, thanks @kettanaito. Have you looked into the work that has been done here? https://github.com/vercel/next.js/tree/canary/packages/next/src/experimental/testmode/playwright
There may be an opportunity to work more closely with the Next.js team on this functionality, especially for use cases like Playwright.
One question, with this template, how i can toggle msw with playwright to run only on test env?
@mrmckeb, thank you. Yes, I've heard about the test mode in Next.js. I don't believe it's the right place to integrate MSW. I will look at it again in the future but it's unlikely I will be recommending it.
@bertoldoklinger, you can toggle it by introducing an environment variable. Start the worker conditionally based on the value of that variable.
// your/app.jsx
if (process.env.SOME_VARIABLE === 'some-value') {
// ...
worker.start()
}
I'm using this config with vitest, but If I try to run a simple test:
test('should pass', function () {
expect(true).toBe(true);
});
I get:
Error: No known conditions for "./browser" specifier in "msw" package
Some suggestion to avoid this issue?
@crisfcodes, you need to configure your Vitest not to load browser modules in Node.js. Afaik, it doesn't do that by default. Perhaps you've enabled that explicitly?
I'm using jsdom env in Vitest, if that is what you mean with enabled, also I'm wrapping the app with the MockProvider but the worker.start executed conditionally. what I did as workaround is to ignore the file that is throwing the error(browser.ts) with Vitest exclusions.
Also I'm having another issues like:
- Infinite browser loading states after manual reload and hot reload/tab switching, it blocks the browser so it's hard to debug, any recommendation for debugging?
- Cannot read properties of undefined (reading 'url')](https://github.com/mswjs/msw/issues/2053) from
browser/index.jsfile... I patched the package adding?torequest?.urland that fixed the issue.
MockProvider reference:
import { PropsWithChildren, useEffect, useState } from 'react';
import { env } from '@/constants/env.mjs';
export const MockProvider = ({ children }: PropsWithChildren) => {
const [mockingEnabled, enableMocking] = useState(false);
const isProduction = env.NEXT_PUBLIC_ENV === 'prod';
const isAppReady = mockingEnabled || isProduction;
useEffect(() => {
const enableApiMocking = async () => {
const isLocalDevelopment = env.NEXT_PUBLIC_ENV === 'local';
const shouldEnableMocking = typeof window !== 'undefined' && isLocalDevelopment;
if (shouldEnableMocking) {
const { worker } = await import('../tests/mocks/browser');
await worker.start({
serviceWorker: {
url: `${env.NEXT_PUBLIC_BASE_PATH}/mockServiceWorker.js`,
},
});
enableMocking(true);
}
};
enableApiMocking();
}, []);
if (!isAppReady) {
return null;
}
return <>{children}</>;
};
Sorry to use this comment for pointing to other issues, I'm just posting what I've got using this code
Does anyone have any example about middleware?
FYI the current example doesn't seem to work when using Turbopack on Next 14 or RC.0 of Next 15. However it works great with the exact version in the package.json here.
Hi I know that this PR is still in progress - I happen to be investigating how to using MSW with NextJS - it appears that this example as it currently is has the same problem that I've run into - MSW mocks seem to work for the first time the endpoint is called, but for subsequent calls the MSW behaviour is lost.
(I get this error message in subsequent calls):
SERVER LISTEN
is fetch patched? YES
GET / 200 in 3124ms
is fetch patched? undefined
⨯ TypeError: fetch failed
at async getUser (./app/page.tsx:15:22)
at async Home (./app/page.tsx:20:18)
digest: "2377642097"
Cause: Error: getaddrinfo ENOTFOUND api.example.com
at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:108:26)
at GetAddrInfoReqWrap.callbackTrampoline (node:internal/async_hooks:130:17) {
errno: -3008,
code: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'api.example.com'
}
GET / 200 in 67ms
Is this maybe something to do with how NextJS is munging fetch for its caching?
Update: short answer is YES.
If we replace our getUser with a call using axios
async function getUser() {
console.log('is fetch patched?', Reflect.get(fetch, '__FOO'))
const result = await axios.get('https://api.example.com/user');
const user = result.data as User;
return user
}
Then our mocking behaviour works fine.
Is it possible to completely opt out of Next's fetch caching?