こんにちは、サイオステクノロジーの遠藤です。
今回は、React Route v7のブラウザ開発環境でMSWを利用する方法について自分で導入するときに少しハマったので、備忘録的な形でまとめておこうと思います。
では始めていきましょう。
React Routerアプリを作成
まずは、React Routeのアプリを作成します。v7からviteで作成できるようになったのでviteを利用して作成しました。
❯ npm create vite@latest
Need to install the following packages:
create-vite@6.3.0
Ok to proceed? (y)
> npx
> create-vite
│
◇ Project name:
│ msw-blog
│
◇ Select a framework:
│ React
│
◇ Select a variant:
│ React Router v7 ↗
git Initialize a new git repository?
Yes
deps Install dependencies with npm?
Yes
作成が完了したら、ディレクトリを移動します。
cd msw-blog
MSWをインストール
MSWのインストールを行いましょう。
npm install msw@latest --save-dev
ワーカースクリプトをpublicディレクトリにコピー
MSWでは、worker scriptをアプリケーションのpulbicディレクトリに配置することでクライアント上でリクエストをキャッチできるようになります。こちらは以下の形でMSWのCLIを利用することで自分のディレクトリにコピーすることができます。
npx msw init ./public
また、以下のようにsaveフラグを付けるとpackage.jsonにpublicディレクトリのパスが記録されるようになり、mswパッケージをインストールするたびにversionに合わせたワーカースクリプトがコピーされるようになるのでおすすめです。
npx msw init ./public --save
// package.json
{
"name": "my-app",
"msw": {
"workerDirectory": "./public"
}
}
公式 : https://mswjs.io/docs/cli/init
Request handlersでモックを定義
Request handlers 関数を利用することで、モックの定義を行うことができます。まずは、mockを格納するためのディレクトリを作成しましょう。React Route v7では、呼び出し先の関係上app以下で定義しておくのが良さそうなので、app/mocksディレクトリを作成して、配置します。
mkdir app/mocks
ディレクトリを作成したら、handlers.tsを作成します。
// app/mocks/handlers.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',
})
}),
]
Integrate する
ちょっと良いタイトルが思い浮かばなかったので、公式の言葉をそのまま持ってきました。要は、MSWは環境レベルで適用されるため、あらゆるフレームワーク、リクエスト ライブラリ、その他のツールと統合できるということみたいです。ブラウザで使用するか、Node.js プロセスで使用するか (またはその両方) を決めて、対応する統合モジュールを作成してアプリケーションに統合することで、どんな環境でも作成したモックを使うことができるとチュートリアルには書いてありました。今回は、ブラウザ用の統合モジュールを作成していきます。
app/mocksにbrowser.tsを作成します。
// app/mocks/browser.ts
import { setupWorker } from "msw/browser";
import { handlers } from "./handlers";
export const worker = setupWorker(...handlers);
app/entry.client.tsxを記述する
本日の本題です。React Router v7にはSpecial Filesというものがありまして、これらのファイルを利用することでアプリケーションの動きを調整することができます。
公式サイト : https://reactrouter.com/explanation/special-files#entryclienttsx
entry.client.tsxはブラウザで最初に実行されるコードを制御できるものになっており、これに先程のブラウザ用の統合モジュールを利用することでMSWを動かすことが可能になります。それではapp/entry.client.tsxに以下のコードを追記します。
// app/entry.client.tsx
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";
import { HydratedRouter } from "react-router/dom";
async function enableApiMocking() {
if (process.env.NODE_ENV !== "development") {
return;
}
const { worker } = await import("~/mocks/browser");
console.info("Starting MSW service worker...");
return worker.start();
}
enableApiMocking().then(() => {
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<HydratedRouter />
</StrictMode>
);
});
});
そうしたら、アプリを起動して動作を確認してみましょう。
npm run dev
開発者ツールで [MSW] Mocking enabled. の文字が見えたらモックが動くようになっています。お疲れ様でした。

まとめ
今回は、React Route v7のブラウザ開発環境でMSWを利用する方法についてまとめました。React Route触りたてというのもあり、entry.client.tsxの存在に気づくまで時間がかかりましたが、この記事が誰かの助けになれば幸いです。
ではまた~