🦾

Vite + React 環境でモックサーバ立ててみた

2023/12/13に公開

MSW(Mock Service Worker)とは?

MSWとは、サービスワーカーを使用してAPIリクエストをインターセプト(乗っ取り)して、定義したレスポンスを返すモッキングライブラリです。
https://mswjs.io/

サービスワーカについては、この方の記事がとても参考になります。

準備

npm installします。

npm i -D msw

mswで用意された導入スクリプト(mockServiceWorker.js)を入れます。
Reactの例だと、通常publicディレクトリに入るようです。

npx msw init public

導入

Vite + React + typescript環境です。
/src/mockに以下のようなディレクトリ構成で構築します。

src/
 ├─ mock/
 │   │   
 │   ├─data/
 │   │   └ recommendsData.ts // モックデータを定義
 │   └─ mock_api/
 │   │    └ recommends.ts // モックサーバの内容を定義
 │   └ handlers.ts // mock_apiで定義した関数を管理
 │     browser.ts // 最終的にページで呼び出すsetupMsw()を定義
 └ App.tsx

mock_apiとdata

モックサーバの動作を記述します。
エンドポイントごとにファイルを作成して、定義したエンドポイントにリクエストが来た時の処理を記述します。
この場合だと、recommendsDataを返しています。

src/mock/mock_api/recommends.ts
import { HttpResponse, http } from 'msw'
import { recommendsData } from '../data/recommendsData'

export const recommends = [
  http.get('/mock/recommends', () => {
    return HttpResponse.json(recommendsData)
  }),
]

レスポンスに使用するデータを定義します。
この場合、型は別途インポートしています。

src/mock/data/recommendsData.ts
import { ItemData } from '@/types/custom/itemData'

export const recommendsData: ItemData[] = [
  {
    title: 'ハリー・ポッターと賢者の石',
    description:
      'ハリー・ポッターは、魔法使いの世界に住む孤児。ある日、ホグワーツ魔法学校に入学することになり、そこで魔法の世界の秘密を知る。',
    category: '映画',
    image: 'https://images-na.ssl-images-amazon.com/images/I/51oqKvX4wZL._AC_.jpg',
    rating: 4.5,
    ratingCount: 100,
    year: 2001,
    duration: 152,
  },
  {
    title: 'ハリー・ポッターと秘密の部屋',
    description:
      'ハリー・ポッターは、ホグワーツ魔法学校で2年目の授業を受ける。しかし、ホグワーツ魔法学校に謎の怪物が現れ、生徒たちが次々と石になってしまう。',
    category: '映画',
    image: 'https://images-na.ssl-images-amazon.com/images/I/51oqKvX4wZL._AC_.jpg',
    rating: 4.5,
    ratingCount: 100,
    year: 2002,
    duration: 161,
  }
]

環境変数

APIリクエストを乗っ取りたくない場合もあるので、環境変数でON/OFFできるようにします。

.env
VITE_NODE_ENV=development
VITE_USE_MSW=true

browser.tsとhandlers.ts

setupMsw関数でsetupWorkerを定義して、exportします。
先ほど設定した環境変数で、実行するかを切り替えます。

src/mock/browser.ts
import { setupWorker } from 'msw/browser'
import { handlers } from './handlers'

export function setupMsw() {
  if (
    import.meta.env.VITE_NODE_ENV === 'development' &&
    import.meta.env.VITE_USE_MSW === 'true'
  ) {
    const worker = setupWorker(...handlers)
    worker.start()
  }
}

mock_apiで定義した関数をhandlersに代入します。

src/mock/handlers.ts
import { recommends } from './mock_api/recommends'
export const handlers = [
	...recommends,
	// 増えた分だけ追加
]

App.tsx

先ほど定義したsetupMsw関数をApp.tsxで呼び出して、起動時に実行するようにします。
これでhttp://localhost:5173/mock/recommendsへのリクエストを乗っ取り、サービスワーカがモックのレスポンスを返すことが出来るようになります(面白い✨)

src/App.tsx
import { setupMsw } from './mock/browser'

function App() {
  setupMsw()
  return (
     // ...略
  )
}

export default App

試す

適当にmock_apiで定義したエンドポイントを呼び出してアプリを起動すると、モックデータが取得できていることが分かります。

npm run dev

ちなみに、最初に「サービスワーカーを使用してAPIリクエストをインターセプト(乗っ取り)して、定義したレスポンスを返すモッキングライブラリ」と記述しましたが、実際にDevToolsでネットワークの項目を開くと、サービスワーカでインターセプトされたAPIリクエストが確認できます。

また、アプリケーションの項目より、mockServiceWorker.jsによってサービスワーカの制御が行われていることも確認できます。

参考

最後に

別でモックサーバのプロセスを立ち上げる必要が無く、比較的簡単に実装出来ました。
サービスワーカを使用してAPIリクエストを乗っ取るという仕組みがとても面白いと思いました。
Storybookでもこの恩恵を受けれるらしいのですが、私があまりStorybookを触った経験が無いので、いつかStorybookでも試してみて、恩恵を受けてみたいと思いました。

Discussion