PageSpeed Insightsで計測してパフォーマンスをチューニングした。 


## これは何？

静的ファイルをランディングページとして表示したとき、パフォーマンスってどうなんだろということで

https://pagespeed.web.dev/

で改善してみました。

特に携帯電話(スマホ)の点数を
30点台から**80点台**
までに改善できたので、その時のTipsをご紹介します。
デスクトップは最初から数値は高かったですが最終的に96点付近まで上昇しました。

![スクリーンショット 2022-03-28 16.48.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423658/cf967b0e-d570-1ba0-2003-56910acf22e2.png)
![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423658/cd28a12d-5312-e53a-7612-26ffd17822b9.png)

重要度☆~☆☆☆でまとめてみました。


### 画像のサイズを表示に適切な大きさする(重要度☆☆☆)

* レスポンシブな画像の箇所もあるかと思いますが、これをするだけでかなり改善を感じられました。

### 画像の画質を落とす(重要度☆☆☆)

* 画質を落とすのも効果ありです。PNGだとファイル容量が大きくなりがちですが、JPEGにすると人間の目にはわからないが容量は減っていることがあります。注意点なのは、不可逆な変換になるので、pngのバックアップは取っておきましょう。また、容量を最適化する無料のオンラインサービスもあるのでうまく活用しましょう。


### 画像を遅延読み込みする(重要度☆☆)

https://github.com/tuupola/lazyload

```html

<img class="lazyload" data-src="logo.png" alt="ロゴ" />

※bodyの閉じタグ直前の方がスコアが高い
<script src="https://cdn.jsdelivr.net/npm/lazyload@2.0.0-rc.2/lazyload.min.js"></script>
<script>lazyload();</script>
```
こんな感じで記載すれば、スクロールに応じて画像を読み込むことができます。

すでに大量のimgタグがあり、全て手作業で変更するのは現実的ではない場合は
サーバー側で書き換えるのもありです。一応サーバー側のリソースを使うのでスコアに影響が多少出ますがそこまで大きいスコアダウンは見られませんでした。
PHP(Laravel)だとDomXpathを用いて書き換えることができます。

参考コード
```php    
    /**
     * lazyload用のHTMLを整形する
     *
     * @param string $code
     * @return string
     */
    public static function imgeConvertLazyLoad(string $code)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->preserveWhiteSpace = false;
        $dom->formatOutput = true;
        libxml_use_internal_errors(true);
        $dom->loadHTML(mb_convert_encoding($code, 'HTML-ENTITIES', 'UTF-8'));
        $xpath = new \DomXPath($dom);

        $imgs = $xpath->query("//img");
        foreach ($imgs as $img) {
            $img->setAttribute('data-src', $img->getAttribute('src'));
            $img->removeAttribute('src');
            $img->setAttribute('class', $img->getAttribute('class') . ' ' . 'lazyload');
        }

        return preg_replace('~<(?:!DOCTYPE|/?(?:html|body))[^>]*>\s*~i', '', mb_convert_encoding($dom->saveHTML(), 'utf-8', 'HTML-ENTITIES'));
    }
```

### 画像やレイアウト計算に影響が少ないCSSは遅延して読み込ませる(重要度☆☆)
https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery?hl=ja

逆言えば、画像やレイアウト計算に影響があるものはheadで読み込ませてください
head内で先に読み込ませる
例: メインのレイアウト、フォントサイズetc

body内で遅延して読み込ませる
例: 背景画像、フォントファミリーetc

```html
<html lang="ja">
    <head>
        // 画像レイアウト計算に影響影響が大きいものは、headタグ内で読み込む
        <link rel="stylesheet" href="/css/メインのレイアウトの.css" />
        <link rel="stylesheet" href="/css/フォントサイズだけの.css" />
    </head>

    <body>
        ~~~
        ~~
        ~
        // 画像レイアウト計算に影響の少ないものはロードが終わってから表示させる
        <noscript id="deferred-styles">
           <link rel="stylesheet" href="/css/背景画像の.css" />
           <link rel="stylesheet" href="/css/フォントファミリーの.css" />
        </noscript>
        <script>
            const loadDeferredStyles = function() {
                const addStylesNode = document.getElementById("deferred-styles");
                const replacement = document.createElement("div");
                replacement.innerHTML = addStylesNode.textContent;
                document.body.appendChild(replacement)
                addStylesNode.parentElement.removeChild(addStylesNode);
            };
            const raf = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
                window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
            if (raf) raf(function() { window.setTimeout(loadDeferredStyles, 0); });
            else window.addEventListener('load', loadDeferredStyles);
        </script>

        <script src="https://cdn.jsdelivr.net/npm/lazyload@2.0.0-rc.2/lazyload.min.js"></script>
        <script>lazyload();</script>

    </body>
</html>
```

### 不要なCSSは削除するか、動的にstyleタグを作成する(重要度☆)

Chormeの開発者ツールのカバレッジで見ることができます。
使ってないCSSは削除しちゃいましょう。

![スクリーンショット 2022-04-18 16.08.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423658/a9ded8e0-3097-7a57-ed2b-6f6b7f4fe282.png)

![スクリーンショット 2022-04-18 16.09.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423658/ee3a1bd4-bc6b-b63e-97dc-728033555097.png)

諸事情で、CSSに定義できず、動的に作成せざるを得ない場合はサーバー側でstyleタグを埋め込んでも良いです。
Laravelであれば、view関数を使うとあっさり作れたりします。


### コードをminify化する(重要度☆)

HTMLそのものもそうですし、CSSやjsもminify化すると多少スコアに影響がありました。
LaravelであればHTMLMinなどのライブラリがあるので、使うと良さそうです。
開発環境では、デバッグしにくいので、本番環境のみなど工夫をした方が良さそうです。

### フォントファミリーをサブセット化する(重要度☆☆☆)
フォントファミリーのファイルは大きくなりがちです。
その理由はギリシャ文字など、普段使用しない文字まで入っているからです。
サブセットされたものを使用しましょう。

### キャッシュを使う(重要度☆☆)
画像がS3にある場合はmax-ageなど適切に設定しましょう。


## 所感
何がボトルネックかと調べて、大きいものから対処していきました。
まだ細かいものはありますが、後々追記していこうと思います。
パフォーマンスを上げるためにあれこれ、テコ入れするとどうしても可読性が悪くなります。
きれいなコードが必ずしもパフォーマンスが良いわけではないと痛感させられました。