🏕️

Vite + React 環境にMock Service Workerを追加する

2023/11/06に公開

今回はVite + Reactの環境にmswを追加する学習メモです

  • MSWのバージョンは2.0.
  • APIはRESTful

ヨロシクオネガイシマス🧑‍🚒

MSW(Mock Service Worker)

モックサーバーを導入するためのライブラリのひとつ
APIのリクエストやレスポンスを乗っ取ることができる
https://mswjs.io/

インストール

$ yarn add -D msw

getting-started

今回はブラウザでのAPIをモック化したいので、
https://mswjs.io/docs/integrations/browser を 参考に見ていきましょう

スクリプトの準備

MSWのスクリプトを指定されたディレクトリに生成

$ npx msw init <PUBLIC_DIR> [options]

develop時に実行したいので、developスクリプトの最初に実行する

package.json
  "scripts": {
    "develop": "run-s msw && vite",
    "msw": "msw init ./public --no-save"
  },

指定したディレクトリ(public)にmockServiceWorker.jsができていることが確認できますね

  • --no-saveオプションはpackage.jsonに./publicディレクトリを出力しなくなるデフォルトオプション
    今回は不要だから出力されなくてok
  • npmコマンドを実行したいのでnpm-run-all を入れときます

セットアップ

環境変数

APIを乗っ取りたくない場合もあるので、環境変数で切り替えられるようにしておく

.env
# MSW を使用するかの設定
# true かつ NODE_ENV=development で有効
VITE_USE_MSW=

接頭辞にVITE_をつけるのはviteのルールっぽいです
vite - 環境変数

setupWorker

モックサーバーのセットアップ
setupWorkerの引数には実際に乗っ取りたいAPIのハンドラを記述します
先ほど設定した環境変数でdevelopモードの時のみ実行するよう分岐します

import { setupWorker } from 'msw/browser';
import { HttpResponse, http } from 'msw';

export function setupMsw(){
  if (import.meta.env.DEV && import.meta.env.VITE_USE_MSW === 'true') {
    const worker = setupWorker(...[
      http.get('/example', () => {
        return HttpResponse.json({ user: { name: 'hanako' } });
      }),
    ]);
    worker.start();
  }
}

setup-workerについて
ハンドラーについて(RESTful用)

呼び出し

開発環境の起動時に上記で用意したsetupMswを実行する

main.ts
import { setupMsw } from '@/mocks/msw'
// msw
setupMsw();

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
...)

確認

実際に起動して確認してみます

$ yarn develop

/exampleが呼ばれるページを見てみると、設定した値が返ってくることが確認できます

{
    "user": {
        "name": "hanako"
    }
}

おまけ

ディレクトリの整理

全部まとめて書きましたが、数が増えると大変なことになるので
ファイルを分けます

public/
 └ src/
   └ mocks/
    ├ handler/
    │ └ example/
    │   └ index.ts
    ├ handlers.ts
    └ index.ts

mocks/handler 配下には エンドポイント毎のディレクトリを切り、それぞれのハンドラーを記述

mocks/handler/example/index.ts
import { HttpResponse, http } from 'msw';

export const handlers = [
  http.get('/user', () => {
    return HttpResponse.json({ user: 'hanako' });
  }),
];

mocks/handlers.tsmocks/handler をまとめた配列を生成

mocks/handlers.ts
import { handlers as exampleHandlers } from './handlers/example';
// 増えた分だけ追加

export const handlers = [
  ...exampleHandlers,
  // 増えた分だけ追加
];

mocks/index.tssetupMswを記述しexportする

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

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

以上です、おつかれさまでした!

Discussion