Nuxt3とMSWの相性が悪いのでjson-serverで代替する
環境情報
- Nuxt3.8.2(SSR)
- Vue3.3.11
- Node.js20.9.0
- json-server0.17
- Laravel10(外部API)
背景と前提情報
Nuxt3でAPIモックを導入したいと思い、ReactやNextで使用していたMSW(MockServiceWorker)をインストールしようとしたところかなり相性がよくないことがわかりました。
なぜ相性が良くないのか
- Nuxt3でHTTPリクエストする際にuseFetch、useAsyncData、$fetchが推奨されている
- MSWが$fetchに対応されていない
参考記事:https://zenn.dev/harusame0616/articles/d497a84a6cb792
一応上記記事ではnodeの--no-experimental-fetchオプションを使用することで導入も可能なようでしたが、今回のプロジェクトではNuxtサーバーからLaravelの外部APIを実行する想定で、その外部APIのみをモックしたかったこともあり断念しました。
今回の構成
上述でも少し触れましたが、NuxtサーバーAPIを経由してLaravelで実装したAPIを実行する構成となっています。今回はLaravel APIの部分のみをモック化していきます。
代替としてjson-severを導入
json-serverをインストールするコマンドを実行します。
npm install --save-dev json-server
mock用データの作成
Nuxtプロジェクト直下にmocksディレクトリを作成し、その配下にdb.jsonとroutes.jsonを作成します。
db.jsonには返却したいレスポンスの固定値を記述します。
{
"user1": {
"data": {
"last_name": "山田",
"first_name": "太郎",
"last_name_kana": "ヤマダ",
"first_name_kana": "タロウ"
}
},
"user2": {
"data": {
"last_name": "山田",
"first_name": "花太郎",
"last_name_kana": "ヤマダ",
"first_name_kana": "ハナタロウ"
}
}
}
routes.jsonにはAPIエンドポイントのマッピングを記述できます。
json-serverは複数階層のルーティング(/api/userなど)を設定できないため、routes.jsonにエンドポイントの変更を記述することで対応する必要があります。
{
"/api/user/1": "/user1",
"/api/user/2": "/user2"
}
json-serverの起動
json-serverを起動するコマンドを実行します。オプションに
$ json-server --watch db.json --routes routes.json
\{^_^}/ hi!
Loading mocks/db.json
Loading mocks/routes.json
Done
Resources
http://localhost:3000/user1
http://localhost:3000/user2
Other routes
/api/user/1 -> /user1
/api/user/2 -> /user2
Home
http://localhost:3000
curlコマンドで実際にレスポンスを取得できるか試してみます。
$ curl -X GET 'http://localhost:3000/api/user/1'
{
"data": {
"last_name": "山田",
"first_name": "太郎",
"last_name_kana": "ヤマダ",
"first_name_kana": "タロウ"
}
$ curl -X GET 'http://localhost:3000/api/user/2'
{
"data": {
"last_name": "山田",
"first_name": "花太郎",
"last_name_kana": "ヤマダ",
"first_name_kana": "ハナタロウ"
}
ルーティングのマッピングも正常に動作していることを確認できました。
Nuxtの設定修正
json-serverを参照するかLaravel APIを参照するかの切り替えを簡単にできるように設定を追加しておきます。
.envの修正
ここではLaravel APIのエンドポイントを指定しておきます。
(今回は例としてhttp://localhost:8080)
NUXT_API_URL=http://localhost:8080
nuxt.config.tsの修正
runtimeConfigの設定を追加します。その他の設定は今回は割愛してます。
export default {
runtimeConfig: {
api: { url: '' }
}
}
package.jsonの修正
scriptsにjson-server起動コマンドを追加します。
{
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev --inspect",
+ "dev-mock": "NUXT_API_URL=http://localhost:3000 nuxt dev --inspect & json-server --watch mocks/db.json --routes mocks/routes.json",
// ~~ 以下省略 ~~
}
}
これでnpm run dev-mock
を実行するとjson-serverとNuxtのビルドサーバーを同時に起動できるようになりました。
コマンド実行の際にNUXT_API_URL=http://localhost:3000
で環境変数の上書きをしているため、useRuntimeConfig().api.url
でソース側の修正はせずに向け先の変更が可能となります。
Laravel APIを参照したい場合はこれまで通りnpm run dev
でOKです。
MSWと比較してのデメリット
- json-server用のプロセスを立てる必要があること
- ルーティングの階層をネストするにはroutes.jsonを使わないといけないところ
- postメソッドを使った場合、db.jsonが書き換わるところ
- middlewaresオプションを使用すれば一応対策可能
- 参考記事:https://qiita.com/unpi/items/4f5951af615db7d19cee
まとめ
Nuxt API側のみaxios等でリクエストしてMSWを採用することも検討しましたが、componentとAPIで別のリクエスト手段を使用するのも抵抗があったので今回はMSWの採用を見送る方針としました。
また、時間があまりなかったのでMSWを上手く導入する方法を深く追及しませんでしたが、MSWがNuxt3の$fetchに対応すれば切り替えを検討したいと思ってます。
Discussion