😁

【まだパフォーマンス改善できてないの!?】GatsbyJSで徹底的に速度改善をした話

2020/11/05に公開

この記事は https://tech-blog.yoshikiohashi.dev/posts/gatsby-speed-kaizen のマルチポストになります。

はじめに

ある日何気なく自分のブログの Light Houseの結果を確認してみた日のことでした。。。

なんと爆速のはずのGatsbyJSのスコアがレッドゾーンになっているではありませんか!!

速度を求めたゆえのGatsbyJSなのにこれはあかん。。。

ということで徹底的に速度改善をしようと思います。

GatsbyJSなにそれという人は

こちらを参考にどうぞ。前に紹介しています。

https://tech-blog.yoshikiohashi.dev/posts/start-gatsby-blog

そもそもサイトが重い原因

原因は様々ですが、よくあるパターンはこんな感じです。

  • 内部で使用している画像が重い(最適化できてない)
  • Unused JavaScriptが数多く存在している(あるある)
  • GTM, Google Adsense 自体が重い(これはしかたない)
  • Script, Linkタグの読み込みが非同期になっていない

大抵は画像が重いだけだったりするので画像の置き場所、最適化できるSaasを検討しましょう。

やったこと【画像編】

内部で使用している画像をUploadcareに移す

何故か内部のプロフィール画像の取得時間に1.37sec (容量は20kbくらいなのに)もかかっていたのでローカルにおいていた内部画像をUploadcareに移しました。リサイズも指定できるので便利。

https://ucarecdn.com/37bf29a4-dcb3-456b-afc0-f34d138c3f77/-/resize/400x/

記事内で使用している画像をリサイズする

記事内の画像はUploadcareに移して1000pxで取得していたので、400pxくらいにリサイズしました。ここは画質が崩れないくらいにうまい具合に調整をしながらやるとバランスがとれます。

大体400 ~ 800くらいが限界値かも。

使用していない画像を削除する

内部の画像の方がホントは早いはずですが、Netlifyは日本にCDNはなくシンガポールが一番近いので、そこで時間がかかっているのかもしれません。

なので使わなくなった画像は削除です!少しでも軽く!

rm -rf static/media/profile.jpg

やったこと【Unused JavaScriptの排除編】

ここが一番重要です!

gatsby-plugin-lodash を導入する

入れるだけで不要な lodash ライブラリを削除してくれます。

下のように記載すると特定の機能を指定して排除してくれるようです。

// gatsby-config.js
plugins: [
  {
    resolve: `gatsby-plugin-lodash`,
    options: {
      disabledFeatures: [`shorthands`, `cloning`],
    },
  },
]

まるごと lodash を使用しているコードを最小限のコードに修正する

よくこんなコードを見かけます。

import _ from 'lodash';

export const hoge = () => {
    const a = 'aaaaAA'
    _.kebabCase(a)
    
    const array = ['a', 'b']
    _.each(array, (str) => console.log(str))
}

こんなやつがいたら打首です!!

lodashはちゃんとライブラリを指定して入れましょう。そうしないとbundleサイズが大きくなってしまいます。

import { kebabCase } from 'lodash/string';

export const hoge = () => {
    const a = 'aaaaAA'
    kebabCase(a)

    const array = ['a', 'b']
    array.forEach((str) => console.log(str))
}

ちなみに自分のブログに4つくらいありました。。。反省してます。。。

gatsby-plugin-webpack-bundle-analyser-v2を導入する

v2とは。。。?と思いましたが、下のように指定するとgatsby develop 後にbundle.js のサイズを表示してくれます。こちらを参考に減らしていきましょう。

// in gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: "gatsby-plugin-webpack-bundle-analyser-v2",
      options: {
        devMode: true,
      },
    },
  ],
}

やったこと【その他編】

linkタグで使用するドメインとpreconnectしておく

例えば uploadcare.com は画像を取得するのに必要なので、事前にサーバと接続しておくとその後がスムーズになるみたいです。

画像取得前にサーバにアクセスしておくイメージです。

他にも重そうなライブラリを取得したりするので色々入れています。

<link rel="preconnect dns-prefetch" href="https://ucarecdn.com" />
<link rel="preconnect dns-prefetch" href="https://ad.doubleclick.net" />
<link rel="preconnect dns-prefetch" href="https://googleads.g.doubleclick.net" />
<link rel="preconnect dns-prefetch" href="https://fonts.googleapis.com" />
<link rel="preconnect dns-prefetch" href="https://www.googletagservices.com" />
<link rel="preconnect dns-prefetch" href="https://www.google.com" />
<link rel="preconnect dns-prefetch" href="https://tpc.googlesyndication.com" />
<link rel="preconnect dns-prefetch" href="https://pagead2.googlesyndication.com" />
<link rel="preconnect dns-prefetch" href="https://b.st-hatena.com" />

scriptタグのライブラリ取得タイミングを非同期にする

asyncをつけると取得を非同期にしてくれます。(これは有名そう)

<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"/>

Web Font を使用してる場合はローカルに保存して使用する

これは必要とわかっているのですが、CSSが面倒でやっていないです。

Google Fonts からDownloadができるので内部に入れてみてはいかがでしょうか。ただ先程の画像の取得に時間がかかるのもあり、内部に入れても解決するのか?という疑問はあります。

速度対策をしてみた結果は。。。!?

34 => 71 か... うーん。なんだかしょっぱい結果に。(まあでも悪くはない結果かな)

原因はまだ Unused JavaScriptにあります。

これはGatsbyJSそもそもで未使用なライブラリを排除できていないと議論されており、まだクローズされていないようです。大人しくフレームワークの進歩を待ちましょう。

結局時代が進化しても、根本的に悩む原因は同じというなんとも切ない。。

ただ残りの原因は、処理速度の問題らしいので無駄処理を見つけてよりシンプルなコードにしていこうと思います。

ちなみに

こちらの記事で書いたCI/CDでの速度改善ですが、これはあくまでビルドした生成物の中だけの話なので、サイトを継続監視する場合は、自分でlighthouse Serverを立てて対応する必要がありそうです。

https://tech-blog.yoshikiohashi.dev/posts/gatsbyjs-lighthouse-ci

僕は純粋に速度がどうなったかを見たいだけので、このままCI/CDでの運用にしています。

【番外編】 Firebase Hosting vs Netlify Hosting

このブログはNetlifyで運用をしているのですが、よくNetlifyのCDNは日本になくシンガポールを通るから遅くなる!という意見を言う人がいます。

実際に日本でなくシンガポールを通っているのか確認してみましょう。

$ traceroute tech-blog.yoshikiohashi.dev
1  10.7.1.254 (10.7.1.254)  2.082 ms  1.417 ms  1.294 ms
2  nas826.p-tokyo.nttpc.ne.jp (210.165.249.204)  3.701 ms  5.120 ms  4.422 ms
3  210.165.249.57 (210.165.249.57)  3.628 ms  4.041 ms  3.676 ms
    if-ae-11-2.thar1.svq-singapore.as6453.net (180.87.98.37)  80.042 ms
~~ 略 ~~
13  * * 138.197.245.11 (138.197.245.11)  80.136 ms```

たしかにシンガポールを迂回してきてますね。うーーん。これは遅くなりそう。

じゃあFirebase Hostingなら早いのか?

適当にFirebaseにデプロイして比べてみました。

速度改善中に比べていたので上記の結果と若干の誤差はあります。

まずは Netlify Hosting !!

お次は Firebase Hosting !!

結果

Firebase Netlify
スコア 73 62

明らかにFirebaseの方が早いですね。ただNetlifyにはCMS機能やCI/CD機能もあるのであとは日本にCDNがあれば。。。といったところでしょうか。

ISSUEを上げてもあまり対応する気がなかったりとか、アジア圏はあまり顧客対象としてないのかもしれません。Netlifyもスタートアップだし、ちゃんとお金出してくれそうなNYとかに投資するよね。

対応されることを夢見て待つことにします。

まとめ

速度改善をやってみた結果、一番効果があったのは未使用JavaScript の排除のおかげでスコアが伸びました。

つまるところJSの極みはwebpack力にあると痛感しましたw

いままでWebpackは避けて通ってきたのでそろっと手を付けないとだめかなーとか考えてます。

ライブラリ選定するときもそのライブラリを入れるとどのくらい重くなるのかも考えて選定しないといけませんね。

Discussion