使用ソフトウェア | バージョン | 備考 |
---|---|---|
Gatsby.js | 4.14.1 | |
React | 17.0.2 | 最新ではない。デフォルトでこれが入る。 |
@mui/material | 5.8.1 |
Gatsby.js
でマテリアルデザインならおそらく最も有名でもっとも楽なのがMUI
だろう
MUI: The React component library you always wanted
Google Search Console
を眺めているとPageSpeed Insights
という評価ツールにてモバイルのLCP
が「不良」ではないが「改善が必要」になってしまっているのは前から認識していた。
このあたりの細かいことは別の記事に譲るとしてGatsby.js
ではMUI
がボトルネックになってパフォーマンスが低下しているという噂を耳にする。
というわけでかなり簡易的...というかパワープレイだがMUI
で速度が遅くなるのか検証をしてみることとする。
正直、こういったパフォーマンスの検証については専門的な知見がないのでわかる範囲でやってみるという記事になることを予め理解してもらえたらと思う。
gatsby
でmy-blog-starter
を新規作成 > MUI
を実装して比較build
した後serve
したページを検証Lighthouse
でパフォーマンスだけ評価するChrome
のシークレットモード(プラグイン等をオフしてくれる)を利用実際のスコアは本番運用してサーバーの反応+ユーザーの統計が必要なのであくまで参考
またDev版でテストするとスコアが不正確(異様に低く)出るので必ずBuildすること。
生成してすぐのスコアがこちら
サーバーの遅延が殆ど無いにせよ98
は凄い。
有名なSEOを話題に扱うようなBLOGやGoogle
運営のサイトでも60前後程度に収まることも多いので本番を想定するならそのあたりを目指したい。
インストールするだけでなにか変わるのかテスト。
インストールコマンドは公式に出ている通り。
npm install @MUI/material @emotion/react @emotion/styled
MUI
をGatsby.js
に乗せる場合はプラグインがあるのでこちらもインストール
gatsby-plugin-material-ui | Gatsby
npm install gatsby-plugin-material-ui@next
gatsby-config.js
のplugins
配列に記載するのを忘れずに。
plugins: [
`gatsby-plugin-material-ui`,
//略
この状態でビルドだけして検証。
検証用のページではインポートもなにもしていない。MUI
をインストールしただけ。
この状態でLighthouse
で検証するとスコアは同様になる。
私の検証では何度かやったがLCP
が0.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
インポートを無駄に増やしただけで画面に描画するコンポーネントは変わっていないが本番サイトだとコレぐらいはインポートすると思われる量になっている。
変化が出た。
スコア自体は微減という感じだがTime to Interactive
の値が0.9s
から4.7s
に低下。
秒数で見ると約3秒はあまりにも大きいような気がするがスコアはそれほど変わらないのはよくわからない。
とにかくインポートが増えると操作ができるまでの時間にロスが発生する模様。
どこで見たか忘れてしまったのだが、アイコンのインポートでスコアが変わるというフォーラム記事を読んだ記憶がある。
上の例にはアイコンが3つ含まれていたため、こちらを削除して再度テストした。
先程のTime to Interactive
がわずかに良くなった。
ただし、このスコアだとアイコンが悪だとは言い切れない。
やはりトータルのコンポーネント数をへらすことを考えるのが優先だろう。
ドロワの例でそのままページ内容を書き換え。
コードは冗長になるので省略するが、インポート+実装でスコアがどう変わるか。
インポート数は11行。
なんとスコアが大きく低下した。
特にLCP
は大幅に低下してしまった。
そもそもここの不合格ラインが2.5s
なのでMUI
の実装だけでオーバーしてしまったと言える。
MUI
のサンプルから個人的によく使うアコーディオンのサンプルを実装してみた。
こちらは描画にコストを使いそう+コード数が多めのサンプルだからという理由。
コードは95行。インポート数は7行。
なんとスコア100
あまりにも差がでてしまった。
確かにこちらのほうがコンポーネント数は少ないが、そこまで大きい差ではない。
実装しているコンポーネントでパフォーマンスの違いがありそうに思える。
web上で別ウィンドウのような動きをするモーダルウィンドウがコストをあげているとも考えられるので、ダイアログコンポーネントのサンプルも試した。
試したサンプルのインポート数13
なので多め。
しかし、なんとスコア100
。
モーダルは関係ないと思われる。
同様に右クリックメニューのようなものも試したが、結果は良いものだった。
ここまでくると細かい検証になってきてしまうが、上でスコアが唯一低かったドロワコンポーネントの別例をいくつか試した。
なんと、殆どのスコアは99
となった。
ドロワーだけが特別ダメということはなさそうだ。
念のため最初に試したスコアが悪かったドロワを再検証したが、こちらだけスコアが低くなる。
もしかするとemotion
を使っているのがコレだけ+SwipableDrawer
という通常のドロワとは違うのでこちらがボトルネックかもしれない。
検証を続けていたら朝になってしまいそうなので、個人的見解を多く含むまとめ。
MUI
をインストールしただけorインポートしただけで驚くほどページが重くなるというわけではないようだ。
ボタンだけとか、ドロワだけのような小さい実装なら殆ど問題なさそうに見える。
まずはコンテンツの中身を軽くすることを考慮してからのほうが良さそう。
MUI
コンポーネントはインポートが増えるごとにスコアが悪くなると思われる。
ただ、これはMUI
に限ったことではないのでインポート文に無駄がないか考えよう。
十分に検証していないがコンポーネント別で重さが明らかに違うものがある可能性がある。
例えば上の例だとSwipableDrawer
が重い可能性がある(検証が不十分だが)
全体でみて特定のページだけスコアが低い場合は単体で検証する必要があるかもしれない。
今回はあくまで単体のサンプルだけでスコアを取った。
実際に稼働しているページクラスのボリュームとなるとまた違った結果がでてくるかもしれない。
MUI
はv5
でパフォーマンスが改善したというのは本当のようだ。
この検証だけで見れば、脱MUIでものすごく大きくスコアが伸びるかというと、単純にそうとは言えないだろう。
MUI
は本当に使いやすいライブラリなので、まずは画像を軽くするとか、スクリプトを削るとか、別の方面からのアプローチで軽量化をしてみるのがいいのではないだろうか。