こんにちは、びわ湖の限界大学生兼フロントエンドエンジニアのお茶です。
長年学生をして、だんだんベテラン学生になってきました。
今回は、自分のポートフォリオサイトのlighthouseスコアを40点上げるために取り組んだパフォーマンスチューニングについて書いていきます。
https://お茶.dev
技術構成
- フレームワーク:Next.js
- デプロイ環境:Vercel
- CMS:MicroCMS
- CSSフレームワーク:ChakraUI,Mantine
- グラフィックス:Three.js
そこまで特殊な技術構成ではないと思います。
お手軽JAMstackアーキテクチャの構成です。
強いて変わっているところを上げるとThree.jsでパーティクルアニメーションが入っているところだと思います。
背景
今回、パフォーマンスチューニングを行ったきっかけとしてはポートフォリオサイトの管理画面を作ろうということで、Bun + TurboRepoのモノレポの新基盤へ移設作業を行なっていました。
もちろんそのまま移設することもできたのですが、せっかくならばこの機会にメンテナンスしておこうといった気分になり今回のチューニングを行いました。
チューニング前のスコア
スコアの結果は44点でした。測定結果からすぐに対応できそうな項目を洗い出してみます。
- 画像のサイズがでかい
- 不要なJSがありそう
- ファーストビューが最適化されてなさそう
改善したこと
画像圧縮
シンプルに画像を圧縮するだけです。使用している画像を全て肉眼で影響の無い範囲で圧縮してwebpへ変換しました。
圧縮にはSquooshが圧縮前後のサイズと画像の劣化具合を比較しながら作業できるので便利です。
https://squoosh.app/
画像最適化
今回は、Next.jsとVercelを使っているのでNextImageを使いました。既存のImage部分をNextImageへと置き換えまともに求めらるPropsを埋めるだけで結構マシになります。
トップビューで表示される画像は遅延読み込みされると困るので
loading=eager
を渡しておきました。
ChakraUIを剥がす
ChakraUIのスタイリングはemotionに依存しているので結局はCSSinJSでスタイルが当たっています。
今回のポートフォリオサイトは大部分をChakraUIで実装していました。
- JSで動的にランタイム時にスタイルを作るのでもっさりする
- 今回のスタイルの大半がJSで生成されている
- Propsにベキベキにスタイルが渡されていてメンテしづらい
CSSフレームワークが悪いわけでは無いのですが今回は実装コストの高い要素も無かったのでそもそも必要なかったです。コンポーネントごとにスタイルを書くにもPropsを荒らすくらいならCSSModulesで十分なので今回の場合はCSSinJSの優位性は薄いと思います。
Chakraを濫用していた部分をCSSModulesで書き直しただけで大幅にJSをダイエットすることができました。
横着に外部からimportしない
ページ内で使用するアイコンやコンポーネントを使用するもののみをimportするようにしました。
import * as THREE from 'three'
このようにthreeを丸ごとインポートするのではなく
import { SphereGeometry } from 'three'
実際に使うものだけをimportすることで少しでも無駄なものを減らしていきます。
altなどの表示に関係ない要素もきちんと埋める
当然ですが、非視覚要素もきちんと埋めるとアクセシビリティは割と簡単に上がります。
パフォーマンスほどの魔境でもないので極力埋めるようにしましょう。
PWA化
スコアには関係ありませんが、PWAの項目が一応あります。
Next.jsを使っているのでNext-PWAでPWA化しました。
https://github.com/shadowwalker/next-pwa
結果
40点アップです!
実際に手元で確認してみても目視でわかる程読み込み速度が改善されていました。
これで通信回線が貧弱であってもスムーズに読み込まれると思います。
余談
web-packのwebpack-bundle-analyzerを使えばビルドされたアプリ内の各パッケージ内容を視覚化して表示してくれます。
更なる改善を目指して解析してみたところ...。
詰んでいました。トップページのパーティクルアニメーションを実装しているThree.jsで埋め尽くされています。
グラフィックスを表示した上でこれ以上のパフォーマンスアップは難しそうでした。