Skip to content

How to apply MSW mocking in Next.js server component? #2451

Description

@chbaefront
// src/components/ExampleServer.tsx

export default async function ExampleServer() {
    const res = await fetch('/api/example');
    const {message} = await res.json();

    return (
        <div>
            <h1>Server Side API Call</h1>
            <p>{message}</p>
        </div>
    );
}
// src/mocks/browser.ts
import { setupWorker } from 'msw/browser'
import { handlers } from './handlers'

export const worker = setupWorker(...handlers)
// src/mocks/node.ts
import { setupServer } from 'msw/node'
import { handlers } from './handlers'

export const server = setupServer(...handlers)
// src/mocks/handlers.ts
import {http, HttpResponse, passthrough} from 'msw'

interface User {
    id: number
    name: string
}

export const handlers = [
    http.get('/api/example', () => {
        return HttpResponse.json({message: 'Hello, MSW!'});
    }),

    http.get('/api/users', () => {
        const users: User[] = [
            {id: 1, name: 'John'},
            {id: 2, name: 'Jane'},
        ]
        return HttpResponse.json(users)
    }),

    http.post('/api/users', async ({request}) => {
        const newUser = await request.json() as Omit<User, 'id'>
        return HttpResponse.json({id: 3, ...newUser} as User, {status: 201})
    }),

    http.get('*', ({request}) => {
        console.log('url', request.url);

        if (/\.(png|jpg|jpeg|gif|svg)$/.test(request.url)) {
            return passthrough();
        }

        return passthrough();
    }),
]
// src/mocks/index.ts
async function initMocks() {
    if (typeof window === 'undefined') {
        console.log("Initializing msw by server");
        const {server} = await import('./node')
        server.listen({
            onUnhandledRequest: 'bypass',
        })
    } else {
        console.log("Initializing msw by browser");
        const {worker} = await import('./browser')
        await worker.start({
            onUnhandledRequest: 'bypass',
        })
    }
}

export default initMocks
/** @type {import('next').NextConfig} */
const nextConfig = {
    experimental:{
        instrumentationHook: true,
    }
};

export default nextConfig;
// src/instrumentation.ts
// import {server} from './mocks/node'; // module not found

export async function register() {
    if(process.env.NEXT_RUNTIME === 'nodejs' && process.env.NODE_ENV === 'development') {
        const { server } = await import('./mocks/node')
        server.listen({
            onUnhandledRequest: 'bypass',
        });
    }
}

How do I apply MSW mocking in Next.js server components?

I set it up like above. The client side is mocked normally, but the server component is not. And I get an error like [MSW] Failed to apply interceptor: the global WebSocket property is non-configurable. This is likely an issue with your environment. If you are using a framework, please open an issue about this in their repository.

Is there a solution or workaround?

I followed this link: mswjs/examples#101 but I still failed. Please help!

git url: https://github.com/katanazero86/nextjs-msw

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions