CreateReactAppにWebVitals計測ライブラリが入ったので試してみた

この記事は[React #2 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/react-2)の12日目の記事です

## 概要

- 最近は[Next.js](https://nextjs.org/)ばかり使ってますが久しぶりに[CreateReactApp](https://create-react-app.dev/)を使ってみたら`reportWebVitals.ts`という見慣れないファイルが生成されていたのを見たのが今日の記事のきっかけです
- [React](https://ja.reactjs.org/)アプリの雛形生成ツールであるCreateReactAppはv4で[WebVitals](https://web.dev/vitals/)の計測ライブラリがデフォルトで組み込まれるようになりました
    - https://github.com/facebook/create-react-app/releases/tag/v4.0.0
- せっかくなのでドキュメントに沿って少し試してみたいと思います

## ファイルの確認

- まずは生成されたコードを見てみましょう
- `create-react-app`コマンドで雛形を生成します

```sh
npx create-react-app --template typescript web-vitals-sample
```

- 生成されたファイルの一覧はこんな感じです

```
.
├── README.md
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── src
│   ├── App.css
│   ├── App.test.tsx
│   ├── App.tsx
│   ├── index.css
│   ├── index.tsx
│   ├── logo.svg
│   ├── react-app-env.d.ts
│   ├── reportWebVitals.ts
│   └── setupTests.ts
├── tsconfig.json
└── yarn.lock
```

- `reportWebVitals.ts`が今回注目するファイルですね
- 中身はこんな感じです

```ts:src/reportWebVitals.ts
import { ReportHandler } from 'web-vitals';

const reportWebVitals = (onPerfEntry?: ReportHandler) => {
  if (onPerfEntry && onPerfEntry instanceof Function) {
    import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
      getCLS(onPerfEntry);
      getFID(onPerfEntry);
      getFCP(onPerfEntry);
      getLCP(onPerfEntry);
      getTTFB(onPerfEntry);
    });
  }
};

export default reportWebVitals;
```

- `web-vitals`というライブラリを使っていろいろ設定してくれています
- `web-vitals`はGoogleChromeが提供するWebVitals計測ライブラリですね
    - https://github.com/GoogleChrome/web-vitals/
- このライブラリの追加とセットアップを事前にやってくれているということのようです

## 使い方

- 使い方はCreateReactAppのドキュメントに載っています
    - https://create-react-app.dev/docs/measuring-performance/
- `reportWebVitals.ts`でexportされた`reportWebVitals`を呼び出して引数に関数を渡して使います
    - 渡した関数が内部で呼び出され各種メトリクスが渡されます
- サンプルにあるように`console.log`を引数として渡してみます

```ts:src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root'),
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals(console.log);
```

- ページを表示するとコンソールにLCPなどのWebVitalsの指標が表示されました！

![スクリーンショット 2020-12-11 18.14.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/dbfe8096-c42a-4274-eb94-68c3cb1368f1.png)

- 取得できる指標は[CLS](https://web.dev/cls/)、[FID](https://web.dev/fid/)、[LCP](https://web.dev/lcp/)、[FCP](https://web.dev/fcp/)、[TTFB](https://web.dev/time-to-first-byte/)の5種類です
    - https://github.com/GoogleChrome/web-vitals/#overview
- サーバに送信したりGoogleAnalyticsに送信するサンプルも掲載されています

```ts
function sendToAnalytics(metric: Metrics) {
  const body = JSON.stringify(metric);
  const url = 'https://example.com/analytics';

  // Use `navigator.sendBeacon()` if available, falling back to `fetch()`
  if (navigator.sendBeacon) {
    navigator.sendBeacon(url, body);
  } else {
    fetch(url, { body, method: 'POST', keepalive: true });
  }
}

reportWebVitals(sendToAnalytics);
```

```js
function sendToAnalytics({ id, name, value }) {
  ga('send', 'event', {
    eventCategory: 'Web Vitals',
    eventAction: name,
    eventValue: Math.round(name === 'CLS' ? value * 1000 : value), // values must be integers
    eventLabel: id, // id unique to current page load
    nonInteraction: true, // avoids affecting bounce rate
  });
}

reportWebVitals(sendToAnalytics);
```

## 試してみた

- 送信されたデータをDBに保存するAPIを作って適当にグラフ表示してみました
    - どういう風に集計するのが有用かはもうちょっとちゃんと考えないといけないですね・・

![スクリーンショット 2020-12-12 3.40.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/a084808a-1ab1-686d-ecfc-6de4214c60a9.png)![スクリーンショット 2020-12-12 3.41.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/a955c826-bc0d-3ddb-4418-cb190d86e488.png)![スクリーンショット 2020-12-12 3.41.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/d094c2ad-dedc-6adc-5227-cb57fe56263d.png)

## まとめ

- CreateReactAppに新しく入ったWebVitalの計測機能はweb-vitalsライブラリのセットアップを事前にしてくれているというものでした
- 取得できるメトリクスを収集するのは簡単なのでそれをどう活用していくか考えていけばよさそうですね