2022-02-22

ローカル環境でNuxt2にMock Service Workerを導入する

kawakami

はじめに

こんにちわ、SMLでエンジニアをしている@kawakami0717です。2年後のLAマラソンに出るために日々走る毎日ですが、最近新しくHOKA のシューズを買いました。HOKAはランニングメーカーで、デザイン性、クオリティ、厚底などに特徴があります。是非何かの参考になれば嬉しいです。

Mock Service Workerとは

Mock Service Workerとは、REST APIリクエストをService Workerが中断して、用意したモックを返すことのできるライブラリです。新機能開発時など、まだREST APIが整っていない時でも、モック用に仮のソースコードを書かなくても、本来のソースコードで動作できる大変便利なライブラリです。また、REST APIの他にもGraphQL APIもモックすることができます

公式サイトはこちら https://mswjs.io/

Mock Service Workerの使い方

 Mock Service Workerは以下のようなモック定義ファイルを作成して使います。以下の rest.getの引数に「モックするリクエストPATH」と「モックデータ」を記述します。モックデータは resの引数にステータスコードとモックデータを記述します

// mocks/handlers.js
import { rest } from 'msw'

export const handlers = [
  rest.get('/user', (req, res, ctx) => {
    return res(
      ctx.status(200),
      ctx.json({
        username: 'admin',
      }),
    )
  }),
]

 モック定義ファイルを作成すると、定義したAPIリクエストが発生したときにService Workerがリクエストを中断させモックデータを返すようになります。ステータスコードも定義することができ、本来のAPIリクエストが返ってきたように振るまうことができます。  モックする必要が無くなった場合は、handlersからモック定義を削除します。もし変更しても変わらない場合は、Service Workerのキャッシュが残っている可能性があるので、Dev ToolsのApplicationを開いてService WorkerをUnregisterしてください

msw | unregist

Mock Service Workerのインストール

 以下のコマンドを実行してmswをインストールします

$ npm install msw --save-dev
# or
$ yarn add msw --dev

 次にモックの定義ファイルを保存するディレクトリを作ります。好きな場所に作成しても大丈夫ですが以下のように作成するのがおすすめです

$ mkdir mocks

 次に作成したディレクトリにhandlerファイルを作成します。このhandlerファイルに上記で紹介したモックの定義を書きます

$ touch mocks/handlers.js

 /user リクエストを中断させて {username: 'admin'} を返すように定義する場合は、 handlers.js に以下のように書きます。

import { rest } from 'msw'

export const handlers = [
  rest.get('/user', (req, res, ctx) => {
    return res(
      ctx.status(200),
      ctx.json({
        username: 'admin',
      }),
    )
  }),
]

 次にService Workerの設定と起動を行うファイルを作成します

$ touch mocks/browser.js

 browser.js を以下のように記述します。setupWorkerでモック定義を読み込みworkerインスタンスを作成しています

// src/mocks/browser.js
import { setupWorker } from 'msw'
import { handlers } from './handlers'

// This configures a Service Worker with the given request handlers.
export const worker = setupWorker(...handlers)

Nuxt2にMock Service Workerを設定する

 Service Workerに登録するセットアップファイルを配置します。このファイルは公開ディレクトリ直下に配置します。Nuxt2の場合は static 配下に配置します。その他の環境で扱いたい場合は、公式サイトを参考にしてください。 Nuxt2にセットアップファイルを配置するには以下のコマンドを実行します

$ npx msw init static/ --save

workerを起動する

 Mock Service Workerを動作させるには、workerを起動する必要があります。Nuxtが起動した時にworkerを起動させるためにpluginを作成します

$ touch plugins/mock.ts

 mock.ts は下記のように記述します。js環境の場合は適宜読み替えてください

export default () => {
  if (process.env.NODE_ENV === 'development') {
    const { worker } = require('../mocks/browser')
    worker.start()
  }
}

 注意:Mock Service Workerは開発環境だけ起動するようにすることをお勧めします。プロダクション環境で使うとユーザーにとって良くないエクスペリエンスになることがあります。  作成したpluginをnuxt.configに定義します

plugins: [
    { src: '@/plugins/mock', mode: 'client' }
],

 Nuxtを起動させるとMock Service Workerが起動しブラウザのコンソールに以下のメッセージが表示されます。

> [MSW] Mocking enabled

 メッセージが表示されない場合は、Service Workerが動いていないことが考えられますので、以下を読み進めてください(エラーの詳細を知りたい場合は、 plugins/mock.tsworker.start() が結果を返すので、その結果から確認できます)

自己署名証明書ではService Workerは起動しない

 Servce WorkerはTLS環境以外では起動しません。また、自前で発行した自己署名証明書(オレオレ証明)でも信用がないため起動しません。これを解決するためにはRoot CAで証明を得たTLSを用意する必要があります。

Root CAで証明の得たローカル環境のTLSを用意する

 ローカル環境のTLSとは、 127.0.0.1 が設定されたドメインに対するTLSを指します。TLSの発行にコストをかけたくない場合はLet's Encryptを利用すると無料でRoot CA証明されたTLSを取得することができます。

Let's EncryptでlocalhostのTLSの発行する

 Let's EncryptでlocalhostのTLSの発行から設定までを雑に紹介します

  1. 127.0.0.1が設定されたドメインを用意する。ex) localhost.example.com
  2. Let's EncryptでDNS ChallengeでTLS発行コマンドを実施
  3. コマンド実施中に指定されたTXTをDNSに設定する
  4. TXTが反映されるまで待つ。例えば1時間くらい
  5. 発行された privkey.pem fullchain.pem をサーバーに設定する

 詳しい方法知りたい方はこちらの記事をご覧ください(Let's Encrypt以外でも mkcert を使ってTrustedなTLSを発行できますが、昨今のOSSで起きた事件などを考えると、悪意のあるコードを仕込まれる可能性も否定できないため、特にTLSの発行についてはOSSの利用は避けたいところです)

 このローカル環境のTLSの運用方針については、Jxckさんの記事を参考にさせていただくと以下が考えられます

  • 開発者は発行した秘密鍵と証明書をコピーして開発環境に設定する
  • 秘密鍵と証明書はプロジェクト間で取り回すことが可能
  • 万が一証明書が漏洩しても、そもそもアクセスはlocalhostに固定となるのと、発行し直せば無効化できて、そもそも長くても3ヶ月で取得し直す必要があるのでリスクが低い(Let's Encryptの場合)

用意したTLSで起動する

 発行した privkey.pem fullchain.pem を以下のようにnuxt.configに設定します

export default {
    ...
    server: {
        https: {
          key: fs.readFileSync(path.resolve(__dirname, 'server/privkey.pem')),
          cert: fs.readFileSync(path.resolve(__dirname, 'server/fullchain.pem')),
        },
    },
}

 Nuxt2を起動しhttpsとlocalhostのドメインでアクセスして、以下のメッセージがコンソールに表示されると成功です

> [MSW] Mocking enabled

 モック定義したAPIをリクエストして定義したモックデータが返ってきていることを確認してください。

 Dev ToolsのNetworkから、そのデータはMock Service Workerで返されたデータなのかを確認することができます。APIのリクエストのヘッダーに x-powered-by: msw と記載がある場合はMock Service Workerから返されたレスポンスになります

MSW | confirm

まとめ

 Mock Service Workerは、REST APIリクエストをService Workerが中断してモックを返すライブラリです。これまでは、API開発を待つかソースコードに仮の実装を入れるなで対応するケースが多いかと思いますが、Mock Service Workerを使うことでAPI開発を待つことなく、ソースコードも仮の実装を入れることなく開発が行うことができます。  Service Workerを使う上でTrustedなTLSを用意するのは少し面倒ですが、自己署名TLSと信頼されたTLSではブラウザの挙動も変わることを踏まえても、この際に切り替えても良いのではと思います。  いずれにせよ、大変面白い仕組みなのとソースコードの品質向上にもつながるライブラリなので是非何かの参考にしていただけたらと思います。

最新の記事