2022-05-31

【Gatsby.js】MUIを使うとパフォーマンスが大きく落ちるのか簡易検証

最近どうしてもモバイルでのLCPがクリアできないので軽く検証

Article Image
使用ソフトウェアバージョン備考
Gatsby.js4.14.1
React17.0.2最新ではない。デフォルトでこれが入る。
@mui/material5.8.1

MUI

Gatsby.jsでマテリアルデザインならおそらく最も有名でもっとも楽なのがMUIだろう

MUI: The React component library you always wanted

MUIを使うとサイトが遅くなるって本当?

Google Search Consoleを眺めているとPageSpeed Insightsという評価ツールにてモバイルのLCPが「不良」ではないが「改善が必要」になってしまっているのは前から認識していた。

改善が必要の画面

LCPの問題

このあたりの細かいことは別の記事に譲るとしてGatsby.jsではMUIがボトルネックになってパフォーマンスが低下しているという噂を耳にする。

簡易検証

というわけでかなり簡易的...というかパワープレイだがMUIで速度が遅くなるのか検証をしてみることとする。

正直、こういったパフォーマンスの検証については専門的な知見がないのでわかる範囲でやってみるという記事になることを予め理解してもらえたらと思う。

検証方法

  • gatsbymy-blog-starterを新規作成 > MUIを実装して比較
  • 一旦buildした後serveしたページを検証
  • ブラウザにインストールしているLighthouseでパフォーマンスだけ評価する
  • ブラウザはChromeのシークレットモード(プラグイン等をオフしてくれる)を利用
  • モバイル版がボトルネックになるので、検証スコアはモバイルのみ

実際のスコアは本番運用してサーバーの反応+ユーザーの統計が必要なのであくまで参考

またDev版でテストするとスコアが不正確(異様に低く)出るので必ずBuildすること。

デフォルトのパフォーマンス

生成してすぐのスコアがこちら

デフォルトのスコア

サーバーの遅延が殆ど無いにせよ98は凄い。

有名なSEOを話題に扱うようなBLOGやGoogle運営のサイトでも60前後程度に収まることも多いので本番を想定するならそのあたりを目指したい。

MUIをインストールしてみる

インストールするだけでなにか変わるのかテスト。

インストールコマンドは公式に出ている通り。

npm install @MUI/material @emotion/react @emotion/styled

Gatsby用プラグイン

MUIGatsby.jsに乗せる場合はプラグインがあるのでこちらもインストール

gatsby-plugin-material-ui | Gatsby

npm install gatsby-plugin-material-ui@next

gatsby-config.jsに記載

gatsby-config.jsplugins配列に記載するのを忘れずに。

  plugins: [
    `gatsby-plugin-material-ui`,
        //略

ビルドして検証

この状態でビルドだけして検証。

検証用のページではインポートもなにもしていない。MUIをインストールしただけ。

結果:かわらない

この状態でLighthouseで検証するとスコアは同様になる。

私の検証では何度かやったがLCP0.1sだけ増えていた。微妙な結果。

ボタンを入れてみる

ボタンを1つだけ配置してみる。

これもMUI公式の最初の使用例にのっているもの。

コードは2行

import Button from '@MUI/material/Button';
//レイアウトの中に次
<Button variant="contained">Hello World</Button>

ボタンが現れた

結果:かわらない

まったくかわらない。

どこかでコンポーネントを一つ読み込んだだけでデータサイズが増えてスコアが落ちるという噂を耳にしたが、解消されていると思われる。

インポートを増やしてみる

ドロワの例にあるインポート例からインポート文だけそのまま追記してみる。

import PropTypes from 'prop-types';
import { Global } from '@emotion/react';
import { styled } from '@MUI/material/styles';
import CssBaseline from '@MUI/material/CssBaseline';
import { grey } from '@MUI/material/colors';
import Button from '@MUI/material/Button';
import Box from '@MUI/material/Box';
import Skeleton from '@MUI/material/Skeleton';
import Typography from '@MUI/material/Typography';
import SwipeableDrawer from '@MUI/material/SwipeableDrawer';

結果:かわらない

スコア1ミリも変わらず。

サーバー応答が高速すぎてこれは検証が無駄かもしれないが、ちょっとインポートしたぐらいでスコアが大きく変わることは無い可能性がある。

もっとたくさんインポート

私が使っているBLOG記事でインポートしている全く同じコンポーネントを更にこちらのページに追記した。

インポートしかしていないが、通常のページ以上に無駄にインポートしていることになると思う。

追加でアイコンもインストール

npm i @MUI/icons-material

インポートを無駄に増やしただけで画面に描画するコンポーネントは変わっていないが本番サイトだとコレぐらいはインポートすると思われる量になっている。

結果:変化あり

変化が出た。

picture 7

スコア自体は微減という感じだがTime to Interactiveの値が0.9sから4.7sに低下。

秒数で見ると約3秒はあまりにも大きいような気がするがスコアはそれほど変わらないのはよくわからない。

とにかくインポートが増えると操作ができるまでの時間にロスが発生する模様。

アイコンのインポートが原因?

どこで見たか忘れてしまったのだが、アイコンのインポートでスコアが変わるというフォーラム記事を読んだ記憶がある。

上の例にはアイコンが3つ含まれていたため、こちらを削除して再度テストした。

結果:スコアが上昇

先程のTime to Interactiveがわずかに良くなった。

picture 8

ただし、このスコアだとアイコンが悪だとは言い切れない。

やはりトータルのコンポーネント数をへらすことを考えるのが優先だろう。

ページ内容を変更

ドロワの例でそのままページ内容を書き換え。

コードは冗長になるので省略するが、インポート+実装でスコアがどう変わるか。

インポート数は11行。

上の例で追加してきた無駄なインポートは削って最小限の構成でテスト

実装の外観

結果:大きく低下

なんとスコアが大きく低下した。

LCPが低下した様子

特にLCPは大幅に低下してしまった。

そもそもここの不合格ラインが2.5sなのでMUIの実装だけでオーバーしてしまったと言える。

念のため別ページも検証

MUIのサンプルから個人的によく使うアコーディオンのサンプルを実装してみた。

アコーディオンのサンプル

こちらは描画にコストを使いそう+コード数が多めのサンプルだからという理由。

コードは95行。インポート数は7行。

結果:かなり良

なんとスコア100

スコア100の結果

あまりにも差がでてしまった。

確かにこちらのほうがコンポーネント数は少ないが、そこまで大きい差ではない。

実装しているコンポーネントでパフォーマンスの違いがありそうに思える。

モーダルウィンドウがだめなのか?

web上で別ウィンドウのような動きをするモーダルウィンドウがコストをあげているとも考えられるので、ダイアログコンポーネントのサンプルも試した。

試したサンプルのインポート数13なので多め。

しかし、なんとスコア100

モーダルは関係ないと思われる。

同様に右クリックメニューのようなものも試したが、結果は良いものだった。

ドロワが重いのか?

ここまでくると細かい検証になってきてしまうが、上でスコアが唯一低かったドロワコンポーネントの別例をいくつか試した。

なんと、殆どのスコアは99となった。

ドロワーだけが特別ダメということはなさそうだ。

念のため最初に試したスコアが悪かったドロワを再検証したが、こちらだけスコアが低くなる。

もしかするとemotionを使っているのがコレだけ+SwipableDrawerという通常のドロワとは違うのでこちらがボトルネックかもしれない。

まとめ

検証を続けていたら朝になってしまいそうなので、個人的見解を多く含むまとめ。

MUI単体ならそこまで重いと言い切れない

MUIをインストールしただけorインポートしただけで驚くほどページが重くなるというわけではないようだ。

ボタンだけとか、ドロワだけのような小さい実装なら殆ど問題なさそうに見える。

まずはコンテンツの中身を軽くすることを考慮してからのほうが良さそう。

ただしインポートしすぎはだめ

MUIコンポーネントはインポートが増えるごとにスコアが悪くなると思われる。

ただ、これはMUIに限ったことではないのでインポート文に無駄がないか考えよう。

コンポーネントで重いものがある可能性はある

十分に検証していないがコンポーネント別で重さが明らかに違うものがある可能性がある。

例えば上の例だとSwipableDrawerが重い可能性がある(検証が不十分だが)

全体でみて特定のページだけスコアが低い場合は単体で検証する必要があるかもしれない。

組み合わせ次第ではわからない

今回はあくまで単体のサンプルだけでスコアを取った。

実際に稼働しているページクラスのボリュームとなるとまた違った結果がでてくるかもしれない。

総合して評価

MUIv5でパフォーマンスが改善したというのは本当のようだ。

この検証だけで見れば、脱MUIでものすごく大きくスコアが伸びるかというと、単純にそうとは言えないだろう。

MUIは本当に使いやすいライブラリなので、まずは画像を軽くするとか、スクリプトを削るとか、別の方面からのアプローチで軽量化をしてみるのがいいのではないだろうか。


この記事のタグ


謎の技術研究部 (謎技研)