如何在Nextjs 13.2.1中使用msw(错误:无法访问服务器上的worker.start,)

oogrdqng  于 2023-06-22  发布在  其他
关注(0)|答案(1)|浏览(150)

我集成了一个模拟API,它基本上发送一个响应对象,其中包含一组消息,这些消息应该与用户名,用户图片等沿着显示在UI(Chatbox)中。
我在使用Next JS 13.2.1**(带有布局的实验应用目录)**设置msw 1.1.0时遇到了一些问题,因为这些更改是破坏性的。但这是我的代码。
到目前为止我的代码是这样设置的

  • src/app/(user)/live-view/page.tsx*
import React from "react";
import ThreadPostList from "../../components/threadList";
 import { worker } from '../../../mocks/browser';

if (process.env.NODE_ENV === 'development') {
  worker.start();
}

async function getMessages() {
  const response = await fetch("http://localhost:3000/api/messages");
  // const data = await response.json();
  return response;
}

async function LiveViewPage() {
  const messages = await getMessages();
  const convertedMessages = Object.keys(messages);
  // console.log(convertedMessages, "ConvertedMessages");
  
  Object.values(messages).forEach(val => console.log(val));

  
  return (
    <div className="border-t border-gray-200 py-4 divide-y divede-gray-200">
      <ThreadPostList />

    
     
    </div>
  );
}

export default LiveViewPage;

我的Msw模拟API在
src/mocks/handler.ts

import { rest } from "msw";
import { UserWithMessages } from "./types";

const mockData: UserWithMessages[] = [
  {
    user: {
      id: "user1",
      name: "John Doe",
      profilePic: "https://example.com/user1.jpg",
    },
    messages: [
      {
        id: "msg1",
        senderId: "user1",
        text: "Hey, how are you?",
        createdAt: new Date("2022-01-01T12:00:00Z"),
      },
      {
        id: "msg2",
        senderId: "user1",
        text: "Did you get my email?",
        createdAt: new Date("2022-01-02T12:00:00Z"),
      },
    ],
  },
  {
    user: {
      id: "admin",
      name: "Admin",
      profilePic: "https://example.com/admin.jpg",
    },
    messages: [],
  },
];

export const handlers = [
  rest.get<UserWithMessages[]>("/api/messages", (req, res, ctx) => {
    return res(ctx.status(200), ctx.json(mockData));
  }),
];

最后我的browser.ts在
src/mocks/browser.ts

"use client"

import { setupWorker } from 'msw';
import { handlers } from './handlers';

export const worker = setupWorker(...handlers);

当我运行服务器时,它抛出一个错误

错误:无法访问服务器上的worker.start。不能从服务器组件点入客户端模块。只能传递导入的名称。

我在哪里以及如何开始我的员工?我是否必须在mocks下创建一个文件并调用那里的服务器并将该组件导入我的page.tsx中?任何帮助将不胜感激谢谢

2jcobegt

2jcobegt1#

自从进入稳定版本以来,我一直在努力让Mock Service Worker在应用程序目录结构中与NextJS保持一致。我已经取得了一定程度的成功,但我怀疑这不是理想的解决方案。我们仍在等待NextJS团队的合法示例实现。
我们不能在服务器呈现的组件上调用worker,因为您看到的正是这个错误。相反,我将我的fetch调用转移到一个共享服务中,它只是typescript:

./services/api-service.ts

async function initMocks() {
  if (typeof window === 'undefined') {
    const { server } = await import('./src/mocks/server')
    await server.listen({ onUnhandledRequest: 'bypass' })
  } else {
    const { worker } = await import('./src/mocks/browser')
    await worker.start({ onUnhandledRequest: 'bypass' })
  }
}

if (process.env.NODE_ENV === 'development') {
  initMocks()
}

export const makeApiRequest = async (path: string) => {
  try {
    const resp = await fetch(path)
    if (resp.ok) {
      const result = await resp.json()
      return result
    }
  } catch (err: any) {
    // handle errors
  }
}

我不知道为什么,但是在像这样的较低级别上实现MSW,并且在实际的react组件之外实现MSW对我来说比试图在页面或布局级别初始化它更成功,因为它是在NextJS pages directory examples中实现的。
这将改变您的页面组件,使其看起来更像顶部:

  • src/app/(user)/live-view/page.tsx*
import React from "react";
import ThreadPostList from "../../components/threadList";
import { makeApiRequest} from './services/api-service';

async function getMessages() {
  const response = await makeApiRequest("http://localhost:3000/api/messages");
  return response;
}

我在这里还注意到一件事,即处理程序正在捕获一个相对路径,这可能也会在服务器端出错。服务器处理程序缺少根URL的上下文,我在那里使用完整路径或路径匹配取得了更好的成功。所以要么:

export const handlers = [
  rest.get<UserWithMessages[]>("http://localhost:3000/api/messages", (req, res, ctx) => {
    return res(ctx.status(200), ctx.json(mockData));
  }),
];

或:

export const handlers = [
  rest.get<UserWithMessages[]>("*/api/messages", (req, res, ctx) => {
    return res(ctx.status(200), ctx.json(mockData));
  }),
];

如果您想使用MSW在已部署的环境或机器以外的其他地方运行Jest测试或其他东西,后者可能会派上用场。
从技术上讲,在您的问题中以及在任何遵循NextJS文档中概述的最佳实践的应用中,我们根本不需要MSW的浏览器实现,因为所有数据都将在服务器组件中获取并用于水合客户端。但是,我将其留在这里是为了在与以前的实现进行比较时提供一些一致性。
在我写这篇文章的时候,我正在使用msw@1.2.1和next@13.4.3

相关问题