Next.jsでmswを利用する。

## 初めに
フロントエンド開発で利用できるモックサーバーを探していたところMSWというものを見つけた。
MSWについては以下記事に詳しくまとめられていたので、こちらを読ませていただきました。

https://zenn.dev/azukiazusa/articles/using-msw-to-mock-frontend-tests

今回は、fetch APIによるhttpリクエストでユーザー情報を取得するデモアプリをNext.js(PageRouter)で作成してみる。
## 動作環境
```
"dependencies": {
        "next": "15.1.3",
        "react": "^19.0.0",
        "react-dom": "^19.0.0"
      },
```

## 実際にやってみる

### Next.jsプロジェクトの立ち上げ
```
npx create-next-app msw-demo-app
```

### MSWのインストール
```
npm install -D msw
``` 

### ワーカースクリプトの作成
既存プロジェクトに導入する際は、publicディレクトリの相対パスを指定する
以下コマンドを実行すると、mockServiceWorker.jsがpublicディレクトリ内に作成される
```
npx msw init public/ --save
```

package.jsonに以下内容が追加される
```package.json
"msw": {
    "workerDirectory": [
      "public"
    ]
  }
``` 

### リクエストハンドラを作成する。
```pages/mock/handler.ts 
import { http, HttpResponse } from 'msw'
 
export const handlers = [
  // Intercept "GET https://example.com/user" requests...
  http.get('https://example.com/user', () => {
    // ...and respond to them using this JSON response.
    return HttpResponse.json({
      id: 'c7b3d8e0-5e0b-4b0f-8b3a-3b9f4b3d3b3d',
      firstName: 'John',
      lastName: 'Maverick',
    })
  }),
]
```

### ブラウザ統合設定
以下のファイルを作成することでNext.jsでMSWを利用できるようにする。
```pages/mock/browser.ts 
import { setupWorker } from 'msw'
import { handlers } from './handlers'

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

```pages/mock/server.ts
import { setupServer } from 'msw/node'
import { handlers } from './handlers'

export const server = setupServer(...handlers)
```

開発環境でのみモックサーバーが機能する
```diff_tsx:pages/_app.tsx
import "@/styles/globals.css";
import type { AppProps } from "next/app";

+ if (process.env.NODE_ENV === "development") {
+   if (typeof window !== "undefined") {
+     import("./mocks/browser").then(({ worker }) => {
+       worker.start();
+     })
+   } else {
+     import("./mocks/server").then(({ server }) => {
+       server.listen()
+     })
+   }
+ }

export default function App({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />;
}
```

### 画面作成　
ボタンをクリックするとfetchによってhttpリクエストが行われる。
```tsx:pages/index.tsx
import { useState } from "react";

export default function Home() {
  interface Iuser {
    id: string;
    firstName: string;
    lastName: string;
  }

  const [user, SetUser] = useState<Iuser>();
  const onClick = () => {
    async function fetchData() {
      try {
        const response = await fetch("https://example.com/user");
        const data: Iuser = await response.json();
        SetUser(data);
      } catch (error) {
        console.error("error", error);
      }
    }
    fetchData();
  };

  return (
    <>
      <h1 className="text-2xl m-1">mew-demo</h1>
      <div className="m-1">
        <button onClick={onClick}>Get Uer Button</button>
        <p>{user?.id}</p>
        <p>{user?.firstName}</p>
        <p>{user?.lastName}</p>
      </div>
    </>
  );
}

```

## 動作確認
```
npm run dev
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779623/4478a914-ac90-1ee8-3576-11358d952c3e.png)
handler.tsに設定したユーザーのデータを取得することができた。

## 参考資料
https://zenn.dev/azukiazusa/articles/using-msw-to-mock-frontend-tests

https://qiita.com/ryotaro76/items/60863ad7d5cbcd271adb

https://qiita.com/mr_noppo/items/5d01088689c95c86cb36