さいきょうの配色 Web サービスが激遅だったので丁寧にパフォーマンスチューニングした

「久々に Lighthouse 確認してみるかな……」
![start.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/a97c36d0-f3eb-9fc0-9f3c-e9568c150ce9.png)


「……！？？」

「にじゅーご……？」
![25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/bb327886-f717-06ad-0c4e-a96c4b1d2b26.png)


「 :innocent: 」



## はじめにおことわり

この記事は `Nuxt.js` で個人開発した Web サービスがパフォーマスンス面でイマイチな状態だったので、それをチューニングした内容をまとめています。

計測は [Lighthouse](https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=ja) でおこない、その改善指針にしたがいチューニングしています。
パフォーマンスチューニングを幅広い視点で汎用的に行うための記事ではありませんので、あらかじめご了承くださいませ。
（逆に、これから個人開発をするような初学者の人には役に立つ情報があるかもしれません）



## さいきょうの配色 Web サービスとは？

:link: [ぼくのかんがえたさいきょうの配色Webサービスを公開した話](https://qiita.com/azukisiromochi/items/4d07e1b247baed01f11b)

以前こちらの記事で紹介させていただきましたが、色に興味があることから開発した Web サービス『 [yum-yum COLOR](https://yumyumcolor.com/) 』のことを指します。

構成は `Nuxt.js` × `Netlify` で、 PWA にも対応した SPA です。
フロントエンド初学者だった当時の僕にしては、まあまあがんばっていたんじゃないでしょうか。



記事の中でも紹介していますが、当時も Lighthouse で計測をおこなっており、そこそこのスコアを出していました。
Lighthouse の仕様は頻繁にアップデートされており、久々に計測したら散々だった……ということです。



## Lighthouse について

冒頭にも紹介した [Lighthouse](https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=ja) は、 Google が開発したオープンソースのツールで、パフォーマンスをはじめとした Web アプリの品質向上に役立つツールです。

以前は Chrome 拡張により利用できましたが、最近では開発者ツール（ Chrome から F12 で表示）にも標準で用意されています。
![devtools.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/fa33d0ec-2289-0180-074a-c58e8e5fecc9.png)

Chrome 拡張の方はモバイルの測定になりますが、開発者ツールではモバイル・デスクトップのそれぞれを測定することが可能です。
また、開発中のアプリ（ URL が localhost:300 など）を測定できるのも開発者ツールのみです。
（スペックの低い PC だと正しく計測できないことがありましたので、どちらも併用するのがよいかもです）



### Lighthouse が提案してくれる改善指針

Lighthouse はパフォーマンスなどを計測するだけでは終わりません。
「なにが原因なのか？　どうすれば改善するか？」を改善指針として表示してくれます。
![next-gen-formats.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/a20c1f92-9873-9455-33c3-04bd10586e00.png)

たとえばこれ。
「アプリが利用している画像のフォーマットが `PNG` や `JPEG` だと重いよ！」といってくれています。
次世代フォーマット（って表現でいいのか？）である `JPEG 2000` や `JPEG XR` 、 `WebP` を使おう！
って感じで。

今回はこれらの指針にしたがいチューニングをしていきます。



## さいきょうの配色 Web サービスのパフォーマンス

冒頭でキャプションを貼りましたが、チューニング前のパフォーマンスは次のような感じです。
![base-performance.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/ba9aeddb-a7e4-41ae-ed50-4e4849273d37.png)

ひどいスコアですね :sweat:
ここから改善させていきます。



## チューニング

### 1. ESLint

これはチューニング以前の問題なのですが、当時このアプリを開発していた頃は本当にフロントエンドの知識が少なく、 ESLint をビルド時に自動実行する設定にしていませんでした。
それどころか Lint を知らなかったわけで……(笑)

実際に Lint を流してみると微妙なところがたくさんあり、とりあえずエラーを解消させています。
それによるものかはわかりませんが、スコアが『 29 』になりました。
![step1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/2dbb37fa-97f9-c4e4-9a00-c54fab00982f.png)




### 2. 次世代フォーマットの画像への差し替え

![next-gen-formats.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/4fa1fedb-3a37-1b6f-55e6-b3840ab80080.png)

これは上ですでに紹介しましたが「画像のフォーマットを新しいものに変えましょう」というものです。
個人的には `WebP` 推しなのですが、 Safari が対応しておらず、 iPhone ユーザーの多い日本では結構痛手です。



#### 改善方法

Safari のみ `JPEG` ……というのも考えましたが、それはそれで JS 側が遅くなりそうなので、一番重い画像（ 189KB のもの）を `PNG` から `JPEG` に変える対応のみ行いました。
（他の画像は比較的軽いですし、透過である必要があるので）
![step2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/68837ca5-b346-39bc-c8e2-5095cbb654cc.png)


うん、気持ちだけスコアアップ :sweat_smile:
ただ、 「Metrics」の `First Contentful Paint` の時間がかなり縮んでいますし、「 Opportunities 」の `Serve images in next-gen formats` が縮んでいます。

どちらも <font color="Red">**赤字**</font> から <font color="Orange">**オレンジ**</font> に変わっていますね。
作ってる身としては、これだけでも気分が悪くないです！



### 3. Ensure text remains visible during webfont load

![Ensure text remains visible during webfont load.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/d0ada3e7-6f3c-cecc-a9d2-ccbdc9658646.png)

これは Google フォントなどのいわゆる Web フォントを使用している場合に、一部のブラウザではフォントの読み込み中にテキストを非表示にするために、テキストが点滅しているように見えてしまうそうです。
「それに対して対策を打ってよ」とのこと。

どのフォントを利用しているのか調べてみると `roboto` というフォントでした。
使った覚えがなかったので `node_modules` に対して Grep すると、犯人は `bulma` でした。
CSS フレームワークである `bulma` の標準スタイルでこのフォントを使っていたようです。



#### 改善方法

[こちら](<https://web.dev/font-display/?utm_source=lighthouse&utm_medium=lr>) に書いてありますが、 `@font-face` スタイルに `font-display: swap;` を指定することで改善するそうです。

```css
@font-face {
  font-family: 'Pacifico';
  font-style: normal;
  font-weight: 400;
  src: local('Pacifico Regular'), local('Pacifico-Regular'), url(https://fonts.gstatic.com/s/pacifico/v12/FwZY7-Qmy14u9lezJ-6H6MmBp0u-.woff2) format('woff2');
  font-display: swap;
}
```

また、 Google フォントであれば URL に `&display=swap` を付与するそうです。

```html
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap" rel="stylesheet">
```

ただ、 `bulma` のフォントにはどちらもうまく適用できませんでした……。

:link: [Nuxt.jsにBulmaを導入して変数を使ったカスタマイズを行う](<https://qiita.com/mnmemo/items/5eb4fb8cbfe17670fd36>)

こちらの記事を参考に `@nuxtjs/bulma` の利用をやめたり試行錯誤しましたが解決方法がわかりません :face_with_head_bandage:
（わかる方いたら教えてほしいです）



### 4. Reduce the impact of third-party code 

![Reduce the impact of third-party code .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/e070fde4-9d15-d7c5-a84a-fa12d9937831.png)


これはわかりやすいですね、サードパーティのコードのインパクトが大きいよ！　だそうです。

しかも一番パフォーマンスに影響を与えているのは……広告。
広告収入は個人開発をしている人にとって重要な収入源なので、これはこのままで(笑)



### 5. Minimize main-thread work 

![Minimize main-thread work .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/8abffee1-ce87-a20b-032e-1daf64f60d08.png)


いかにもパフォーマンスという項目がきました。
メインスレッドのロードに要した時間の内訳です。

これを見ると分かるとおり、 `Script Evaluation` がもっともロードに時間がかかっています。
実はスクリプトのロード時間に関しては、次の項目で詳細がわかるようになっているのでそちらを見てみましょう。



### 6. Reduce JavaScript execution time

![Reduce JavaScript execution time.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/b37042d9-879d-dc9e-c4f5-8d157078245a.png)


JS の解析、コンパイル、および実行がかかっているということです。
デフォルトではサードパーティのコードも表示されているので、右上のチェックボックスを外すと自分のコードのみ表示することができます。



#### 改善方法

まずは JS のコードを分析してみましょう。

```javascript:nuxt.config.js
/*
 ** Build configuration
*/
build: {
  analyze: true,
},
```

`nuxt.config.js` にビルドオプションを追加し、アプリをビルドしましょう。

```shell
$ yarn run build
```

するとブラウザに次のような画面が表示されます。
![yum-yum-color_.nuxt_stats_client.html.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/598d9ca5-c6ae-94d6-d63b-d71c767da866.png)


これはプロジェクトで利用されているコードの割合を示しています。
画面内で大きく表示されているものほど、その容量も大きくなります。

「……Font Awesome。おまえだったのか」

さいきょうの Web 配色サービスでは、ヘッダーに Twitter や GitHub 、それにブログ用のリンクを用意しており、そこで `Font Awesome` のアイコンを利用しています。



それなのに、利用の仕方は……こう。

```javascript
import { fas } from '@fortawesome/free-solid-svg-icons'
```

面倒くさがり屋の自分を恨みたくなる設定です :sob:

これをちゃんと、

```javascript
import { faBlog } from '@fortawesome/free-solid-svg-icons'
```

として利用しました。
![yum-yum-color_.nuxt_stats_client.html (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/446f1019-f44b-3974-3211-9db04676eb67.png)

おー `Font Awesome` 小さくなりましたね。

スコアは……
![step5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/66152983-1598-75f9-2728-92b50dd24df1.png)


これはまあまあ改善されましたね！
やっと許容範囲といったところでしょうか。



## その後も色々と試しましたが……

![step5-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317946/941f67de-1e4f-4bfc-c557-31dfb788ad77.png)


逆に下がってしまったり……安定しません。

さいきょうの Web 配色サービスでは配色を扱うその特性上、インライン SVG を利用しているため一つのファイル容量が大きくなるなど、どうにもこうにもうまくいきませんでした。



### ただし別の方法でパフォーマンスを担保している

このアプリが遅いのは SPA は初期の読み込みに時間がかかるという特性がダイレクトに響いています。

それを解消する一つの方法として PWA があります。
現にこのアプリも 2 回目以降の表示は高速（というか爆速）、 Lighthouse のスコアほど遅い印象は受けないと思います。
（自分で言う）

これから個人開発をはじめるかたは PWA を意識してみるのもいいかもしれません。



## おわりに

この記事は企画とタイトルを先に思いつき、チューニングしながら記事を書き進めていきました。
チューニングがバッチリな結果であれば良かったのですが、実際はそうもうまくいかないもので…… :sweat_smile:

パフォーマンスチューニングの技術記事としては微妙なものですが、Lighthouse を使ったことがない人や、ソースコードの解析を知らない人にとって少しでも役に立てば幸いです :yum: