なぜMock Service Workerなのか。入門編

# 概要

* フロントエンド開発をしている際にバックエンドの開発中にAPIの挙動からフロント側の挙動を確認したい場合があると思います。
* その際に、[MSW](https://mswjs.io/)を使用するとかなり便利に開発ができる為、今回はMSWについて、またその仕組みを深ぼって行きたいと思います。

## Mock Service Workerとは

* Mock Service Workerでは**Service Worker**を使用しリクエストを返すため、**別プロセスでローカルサーバーを立てることなく**簡単に利用することができます。

**Mock Service Workerのリクエストフロー**

* 動きとしては、fetchイベントを介してアプリケーションのRequestをリッスンしておき、それらの要求をクライアントサイドライブラリに送信し、応答するワーカーにモックされた応答がある場合はそれを送信するServiceWorkerを登録し、Responseを送ります。

![スクリーンショット 2022-06-17 23.14.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/4dc28983-d2a7-fc01-b8de-0e5c6b5e41d9.png)

[引用元](https://mswjs.io/docs/)

### Service Workerってなんだろう

* Service Workerは基本的にWebアプリケーション、ブラウザ、およびネットワークの間に配置されるプロキシサーバーとして機能するJavaScriptのアセットです。
* ネットワークリクエストを傍受し、ネットワークが利用可能かどうかに基づいて適切なアクションを実行し、サーバー上にあるアセットを更新することを目的としています。
* また、プッシュ通知とバックグラウンドのAPIへのアクセスも許可されています。
* セキュリティ上の理由から、サービスワーカーはHTTPSでのみ実行されます。
* また、Service WorkerはWebページ/サイトとは独立したライフサイクルの中で動作するので、オフライン状態でも、必要があればService Workerが作動する動きとなります。

#### Service Workerのライフサイクル

* Service Workerにおいてライフサイクルという概念があり、そのイベントについて記述してきます。Mock Service Worker中では意識することはありませんが、こんな動きをしている程度に覚えておくとよいでしょう。

##### 6つの状態

* Service Workerでは、**parsed**, **installing**、**installed**、**activating**、**activated**、**redundant**の6つの状態があります。

###### parsed

* 初期状態を指します。
* Service Workerがまだインストールされておらず、Service Workerとして呼び出された処理が読み込まれたくらいの状態です。

###### installing

* Service Workerをインストールしている最中の状態を指します。
* 新規インストール/更新されている場合もこの状態となります。
* また、すでにService Workerがインストールされており、更新もない場合には**activated**までスキップされます。

###### installed

* **installing**フェーズを通過した状態です。
* Service Workerのインストールには成功していますが、まだService Workerは有効になっていません。

###### activating

* Service Workerの新規インストール時には**installed**からすぐにこの状態となります。
* 更新の場合は、古いService Workerに代わり新しいService Workerが有効になります。

###### activated

* Service Workerが、対象のWebページ/サイトを問題なく制御下に置いた状態です。
* この状態でService WorkerはWebページからのリクエストに反応するfetchや、Webページ/サイトからのメッセージを受け取るmessageイベントを待つことができます。

###### redundant
* installイベント中にエラーが発生場合や、新しいService Workerと置き換えられた場合にService Workerが無効となった状態を指します。

[引用元](https://www.codegrid.net/articles/2016-service-worker-1/)

## Mock Service Workerを使うと何が嬉しい？

* **JSON Serverとよく比較されるのですが、JSON Serverとの違いは、mockサーバ用のエンドポイントにリクエストを向ける必要がありません。**
* **mockサーバ用のプロセスを別で立てる必要がないこと。**
* **モックの動作確認においてDevToolsのNetworkタブから、インターセプトしたリクエストを確認することができる。**
* **RESTやGraphQLのAPIに対応することができる。**

## 使用方法

### インストール方法

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

### Mock Service WorkerのService Workerを生成

* Service Worker のコードをプロジェクトの公開ディレクトリに追加します。
* npx msw init <公開ディレクトリ> --save でService Workerが生成されます。
* 下記を実行すると/publicにmockServiceWorker.jsが生成されます。

```
npx msw init public/ --save
```

### モックAPIの作成

* あとは、実際のmockを作成していく形になります。
* 下記は、**POST /loginリクエスト**をモックするモック定義ファイルの例を示しています。
* setupWorkerの中にモックのAPIを定義し、worker.start()を実行することでモックAPIに合致するリクエストは Mock Service WorkerがインターセプトしモックAPIに書いている値をレスポンスすることができます。

```src/mocks.js
import { setupWorker, rest } from 'msw'
const worker = setupWorker(
  rest.post('/login', (req, res, ctx) => {
    const isAuthenticated = sessionStorage.getItem('username')
    if (!isAuthenticated) {
      return res(
        ctx.status(403),
        ctx.json({
          errorMessage: 'Not authenticated',
        }),
      )
    }
    return res(
      ctx.json({
        firstName: 'John',
      }),
    )
  }),
)

worker.start()
```

# 最後に

* 今回は、Mock Service Workerについてその仕組みとなぜMock Service Workerなのか、何が嬉しいのかという観点でまとめていき、最後にちょっとした使用方法について記載する流れとなっております。
* 今までフロント開発時にmockで困ったこと、もしくは新規開発を始めたフロントのプロジェクトにおいてMock Service Workerのメリットが刺さりそうであれば導入を検討してみてはいかがでしょうか。

# 参考

https://mswjs.io/

https://www.codegrid.net/articles/2016-service-worker-1/

https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API