使用ソフトウェア | バージョン | 備考 |
---|---|---|
Gatsby.js | 5.0.1 | |
React | 18.2.0 | |
MUI | 5.10 |
こちらは備忘録記事であり、厳密に調査した記事ではない。
したがって解釈が誤っている箇所やもっと良い解決策があるかもしれないのでご理解頂いた上で読んでもらえればと思う。
本サイトのモバイルサイトのスコアはかねてから低かった。
例えばローカルの早い環境で性能評価(Lighthouse
)しても
真っ赤である。
しかしコレに関しては、そもそもスコア自体が低めに出る(低スペでアクセスする前提のスコア)と言われており限界だと考えていた。
そもそも以前より様々な対策をしていたが、Gatsbyが5になったタイミングで「どのコンポーネントが重いのか」を試していたところ1つ発見があった。
モバイルorデスクトップ判定で表示/非表示がスイッチするコンポーネントを削る度スコアが目に見えて上がるという点。
これはもしかして...
という仮説に至った。
そもそもどういう実装だったのか。
//isMobileSizeはMUIのuseMediaQueryを使ってtrue/falseを格納
{isMobileSize &&
<>
<MobileAds />
</>
}
こんな風にモバイルかどうかという判定をJSで行い、それをJSXの条件にしてタグをレンダしているだけである。
たったこれだけに気づくために何日も消費したがこれがダメだった。
通常は判定のコードが悪いと疑うと思う。
次の3種類を別々に実装して性能を調べた。
useMediaQuery()
を使うwindow
オブジェクトを使う詳しくは省略するが、そのどれもがダメだった。
1つだけ明らかなのは、どの方法を使ってもレンダー完了後にtrue/falseが帰るという点だ。
つまり、このコードをトリガーにコンポーネントを読み込んでいると
1度レンダ完了してからモバイル/デスクトップでスイッチするコンポーネントを読みに行くということになっている(おそらく)
window
オブジェクトをwrapRootElement
というかなり親側に近い場所で仕込んでも遅いということがわかった。
というわけでロードがブロックされておりサイトが遅いと評価されていたと結論付けた。
結果的にMUI
のResponsive values
を使うことで遅延していたと思われる箇所が殆どなくなった。
コレは何をしているのかというと、要するにsx
のスタイリングを画面サイズ別で分けるものだ。
実際にここで稼働しているものから一部取り上げると
<Box sx={{
display: "none",
[theme.breakpoints.down('xl')]: {
display: 'flex',
height: "100px"
},
}}>
</Box>
このように特定の画面サイズで表示が切り替わる使い方。
今回はこの解説ではないので詳しくは書かないが、とにかくこれでよかった。
上の例を使って表示/非表示を切り替えるには殆どの人がdisplay: "none"
を使うだろう。
React
ではわざわざコレを使うとタグそのものは描画されたまま見た目だけ消えるのでよろしくないと考えていた。
だが、上のようにJSXの条件文で切ってしまうと逆にスコアが下がるということがわかった。
あまり詳しくないので正直わからないのだがMUIのスタイリングはCSSのコードをつかいやすくしただけではないだろうか?
というわけでメディアクエリというものがCSSで使えそうだ(あくまで予想)
メディアクエリーの初心者向けガイド - ウェブ開発を学ぶ | MDN
Bootstrap
のブレイクポイントなども使えるのではないだろうか。
Breakpoints (ブレイクポイント) · Bootstrap v5.0
こちらはすべて試していないので参考までに
私のサイトではGoogle Adsense
コードにはJSXの条件でレンダリングを継続している。
そもそも広告はdisplay: "none"
を使わないようにとの言及がある上に、これを使ってしまうと広告コード自体がエラーを吐いて画面全体が真っ白になるからだ。
ただし、上で述べた通りJSX側でモバイル判定して挿入しているのでサイトのスコアを落とす要素になっている。
最初に上げた画像と比較すると
TBTは半減、LCPも1/3になるというとんでもないスコアアップだ。
サーバーの性能や混雑具合でスコアはブレるので注意。
まさかたったこれだけでスコアが改善するとは思っていなかった。
1枚目の画像ですでに解決済みではあるのだが、遅れて表示非表示される箇所が減ったためCLS
も大幅に向上している。
なんかロード時もっさりしている人は是非ためしてみてほしい。