| 使用ソフトウェア | バージョン | 備考 |
|---|---|---|
| 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/styledMUIをGatsby.jsに乗せる場合はプラグインがあるのでこちらもインストール
gatsby-plugin-material-ui | Gatsby
npm install gatsby-plugin-material-ui@nextgatsby-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は本当に使いやすいライブラリなので、まずは画像を軽くするとか、スクリプトを削るとか、別の方面からのアプローチで軽量化をしてみるのがいいのではないだろうか。
