Gatsby製のランディングページ(LP)のパフォーマンス改善
みなさんこんにちは!アルダグラムでエンジニアをしている今町です。
弊社では、サービスサイトの LP ページ・コーポレートサイトのような静的サイトで Gatsby を利用しています(Gatsby とは React ベースの SSG フレームワークです)
私がアルダグラムに入社して初めて行った仕事が、Gatsby 製の LP ページのパフォーマンス改善でした。入社から 3 ヶ月が経過し、当時を思い出しながらどうやってパフォーマンス改善を進めていったか共有したいと思います。また、Gatsby 製のサイトを運用している方にとって、少しでも参考になったら嬉しいです 🥰
現状を知る
まずは、Gatsby 製のページのパフォーマンスがどうなっているか現状を理解するところから始めてみましょう。
Google が提供している PageSpeed Insights を利用してパフォーマンスを含めた各種指標を測定できます。公開されている Web ページの URL を入力して分析を開始します。
最初は、以下のようにパフォーマンスが真っ赤になっていました… 😭
パフォーマンスのセクションの各種指標の意味は、以下のとおりです。
詳細は診断の欄に出ているので、主だった改善ポイントを以下で確認していきます 💪
診断結果から改善ポイントを洗い出す
以下では、診断結果から改善できるポイントをピックアップした上で、解決策を例示したいと思います。
1. 次世代フォーマットでの画像の配信(高圧縮な画像フォーマットへの置換)
Gatsby で画像データを扱う場合、 gatsby-plugin-image
プラグインを使うことで複数サイズ・フォーマットの画像をビルド時に自動生成し、ユーザー画面(PC・スマホ)に応じて最適なサイズの画像を表示できます。これにより、開発者側は特に意識することなく、画像の最適化を行うことができます。
<StaticImage>
という専用のコンポーネントが用意されているので、画像を表示したい場合は <img>
の代わりとして使用します(詳しくは公式ドキュメントを参照のこと)
しかし、別の React 関連のパッケージを利用しており、そのパッケージ内部で素の <img>
タグが使われてしまっていると、Gatsby の画像最適化の恩恵を受けられません。これが原因で、スコア悪化しているという結果が出ていました。
解決策 1: 該当の React パッケージの置き換え
根本解決としては、該当の React パッケージを置き換えて <StaticImage>
を使う形に改修するという方法がまず挙げられます。ただし、これは実装コストがかかるので、工数と相談になります。
解決策 2: 画像ファイルを高圧縮フォーマット WebP に置換
暫定対応になってしまうのですが、高圧縮の WebP の画像に差し替えることで、描画する画像サイズを圧縮できます。今回は時間をかけられなかったので、この解決策を取りました。
2. オフスクリーンの遅延読み込み(画像の読み込み遅延)
多くの Web サイトでは、ページを開いた際に表示されるのはページ上部で、ユーザーは画面をスクロールして、下に隠れているコンテンツ(オフスクリーン)を見ていくことになると思います。
だとすると、ページ内の画像を一気に読み込まず、ブラウザに表示されている画像だけ先に読み込むことでパフォーマンス改善できそうですよね(このアラートはそれを指しています)
gatsby-plugin-image
プラグインを使って画像を描画している場合は、遅延読み込みを自動でやってくれます。つまり、開発者側は特に意識する必要はありません。
問題になってくるのは先程と同様、別の React 関連のパッケージを利用しており、そのパッケージ内で素の <img>
タグが使われてしまっているケースです。この場合、開発者側で lazy loading するように設定してあげる必要があります。
解決策: lazy loading の設定を追加
対応としては簡単で、<img>
タグに loading=lazy
の設定を追加するだけです。
3. レンダリングを妨げるリソースの除外(Google フォントの読み込みを最適化)
Gatsby では gatsby-omni-font-loader
プラグインを使って、Google フォントなどの Web フォントの読み込みを最適化しています。このプラグインが使われているにも関わらず、blocked rendering になってしまっていてアラートが出ていました。
調べてみると、このプラグインの現存するバグであると報告されています。
解決策: 該当パッケージにパッチを適応する
以下の generators/getFontConfig.tsx
と components/AsyncFonts.tsx
に修正が必要です。
- Original
- 修正版
オリジナルの npm パッケージにパッチを当てたい場合は、以下のパッケージをインストールし、
npm install --dev patch-package postinstall-postinstall
package.json ファイルに以下のカスタムコマンドを追加します。
{
"scripts": {
"postinstall": "patch-package"
...
}
}
その上で、修正版のコードの通りに node_modules 配下にあるファイルを修正します。
最後に、以下のコマンドを実行して、パッチファイルを作成します。
npm run patch-package gatsby-omni-font-loader
こうすることで、npm install が実行された後に、必ずパッチファイルが適応されるようになります。
4. コードサイズの圧縮(不要なパッケージの削減)
コードサイズを圧縮することで、ページを開いたときの読み込み速度を改善できます。Gatsby 向けに webpack のバンドル解析ツールが提供されています。
以下は解析結果の例になります。モジュールサイズが大きなものから中身を確認し、コードサイズを削減できないか検討します。React のパッケージなど必須のものは削減できないとして、やたら大きなサイズのモジュールが存在することがわかります。今回のケースでは、axios を使っていることでモジュールサイズが肥大化していました(これはあくまで一例です)
解決策: fetch API もしくは redaxios を採用する
axios は HTTP クライアントのパッケージです。Web サイトの場合、ブラウザ標準の fetch API が用意されているので、npm パッケージである axois を導入する必要はありません。なので、シンプルに fetch API に置き換え、axios をコードから排除することで、コードサイズを圧縮できます。
もしくは、redaxios というパッケージを使う選択肢もあります。redaxios は fetch API を内部的に使用してインターフェイスは axios に合わせてあるパッケージです。こちらのほうがコードの変更点を減らせるので、移行はしやすいでしょう。
5. gzip 圧縮して配信
gzip 圧縮したうえで Web サイトの配信を行います。ブラウザからリクエストされた JavaScript や CSS ファイルサイズを小さくできるので、結果としてダウンロード時間を短縮できます(以下は AWS の CloudFront の場合)
Web サイトのホスティングに何を使用しているのかに依存するため、解決策の詳細は割愛します。
まとめ
いかがでしたでしょうか?今回紹介したのは、以下の 5 点になります。Gatsby に限らず汎用的に Web サイト構築時に意識したい内容だと思います。
- 高圧縮な画像フォーマットへの置換
- オフスクリーンの遅延読み込み
- レンダリングを妨げるリソースの除外
- コードサイズの圧縮
- gzip 圧縮して配信
気になる結果ですが、真っ赤だったパフォーマンスのスコアが 10 ポイント以上改善できました。劇的に改善したかというとそうではないのですが、地道な積み重ねで Web ページをより良い状態にしていきたいですね。
もっとアルダグラムエンジニア組織を知りたい人、ぜひ下記の情報をチェックしてみてください!
株式会社アルダグラムのTech Blogです。 世界中のノンデスクワーク業界における現場の生産性アップを実現する現場DXサービス「KANNA」を開発しています。 採用情報はこちら herp.careers/v1/aldagram0508/
Discussion