7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Web Speed Hackathon 2022をやってみた

Last updated at Posted at 2022-11-29

11月1日から27日まで開催されていた、webパフォーマンス改善のコンテスト「Web Speed Hackathon 2022 Public」に飛び入り参加してきました。

仕事の方ではバックエンド側ということもあり、フロントのパフォーマンス改善についてあまり詳しくはなかったのですが、先駆者の方々のブログやリポジトリを拝見しながらなんとか取り組んでみました。

初回計測は1点...

とりあえずLighthouseで計測してみましたがまさかの1点!
動作を確認するために操作するのにもストレスがかかるレベルの重さでした
fe75e0dae10e9f5a90a348b0ee3bdac7.png
これをなんとか改善していきましょう。

webpack.config修正

まずはビルドをproductionとdevlopmentに分割するために、以下の構造と設定にしました。

ディレクトリ構成
root/
 ├ webpack.common.js // 汎用設定
 ├ webpack.dev.js    // 開発用設定
 ├ webpack.prod.js   // 本番用設定
 └ webpack.server.js // サーバーサイド用
package.json
"build": "yarn build:server && webpack --config webpack.prod.js",
"build:server": "webpack --config webpack.server.js",
"build:dev": "yarn build:server && webpack --config webpack.dev.js",
"build:watch": "yarn build:dev --watch --progress",

webpackのファイル同士の設定をマージすることが出来る webpack-mergeというモジュールを使用し、本番・開発用に汎用設定をマージすることでコマンドで使い分けることが出来るようにしました。


次に、devlopmentにwebpack-bundle-analyzerを導入しバンドルされたファイルのサイズを可視化します。こちらが出力結果です。

before.png

表示されているsizeの概要は以下の通りです。

  • stat size: 圧縮前のソースコードのサイズ
  • parsed size: コンパイル後のバンドルファイルのサイズ
  • gzipped size: gzip圧縮後のサイズ

とりあえず置き換え可能でありサイズが大きい物から削っていきました。

バンドルサイズを削る

Zengin-codeをモジュールからAPIへの取得に

parsed size: -約3.1MB
zengin-codeは一部で使用されるダイアログコンポーネントでのみ使用されており、すべてのページで使用されているわけではありません。そのため、ダイアログ起動時のタイミングで全銀システムが提供するAPIからデータ取得を行う方式にしました。

ブラウザ対応関連のものを無くす

parsed size: -約1.23MB
レギュレーションにGoogle Chrome 最新版での動作が担保出来ればよい、と記述されていたため古いブラウザ対応のために使用されている以下moduleを削除しました。

  • core-js
  • es5-shim
  • es6-shim
  • es7-shim

Fort AwesomeをモジュールからSVGへ

parsed size: -約788KB
アイコンにはFort Awesomeというアイコンフォントを提供するサービスが使用されていますが、アプリケーションでは3カ所でしか使用されていなかったため削ります。
モジュールによる提供だけではなくsvgによる提供を行っていたため、こちらに変更しました。

Momentjsからdayjsへ

parsed size: -約689KB
Momentjsはバンドルサイズが大きいため、互換性が高くMomentjsと比べサイズの小さいDayjsに置き換えました。
また、サイズという観点以外にもMomentjsは2020年にメンテナンスモードに入っているためこちらの点からも置き換えるべきでしょう。

lodashをやめる

parsed size: -約480KB
lodashで使用されているほとんどのメソッドは、ES20xxで追加されたメソッドを使用することで置き換え可能です。
下記のリポジトリを参考にしながら置き換えていきました。

バンドルサイズ変更後

after.png

変更前の 9.49MBから1.98MBまで削ることが出来ました!🎉
これ以外にもaxiosの削除・Preactの導入なども考えられましたが、今回は時間と知識の問題でここまでは行いませんでした...

画像・フォント最適化

画像最適化

imagesフォルダが85MBとかなり大きいのでこちらを最適化していきます

デフォルトでは画像をトリミングするコンポーネントを使用することで、使用箇所に合わせたリサイズを行っていましたが、最初からサイズに適した画像をこちらで準備すればコンポーネントで処理を行う必要がありません。

画像最適化ソフトは使ったことがなかったので、どれを選択すれば良いか困りましたが今回は「squoosh」を使用しました。採択理由は@squoosh/cliを使用することで複数画像をまとめてリサイズ・変換が可能だったためです。

squoosh-cli --webp '{quality: 70}' *.jpg

@squoosh/cliの使用方法に関してはこちらが参考になりました

全ての画像をリサイズ・圧縮し、jepgからwebpに変換することで85MB -> 225KBまで削ることが出来ました

フォント最適化

一部のページでwebフォントが使用されていましたが5.8MBと大きいのでこちらも削ります。まずはttfからwoff2に変換します。woff2は初めて知りましたがwoffと比べて 圧縮アルゴリズムとしてBrotli方式を採用していることで、woffと比べて12%程度圧縮率が高いらしいです。

さらに、フォントを使用している個所を確認すると数字と一部記号のみでしか使われていないためサブセット化を行い、使用されていないフォントを削除することでサイズを5.8MB -> 3.8KBまで削れました。

その他

gzip圧縮を行う

バックエンド側のレスポンスをgzip圧縮してから配信することでデータサイズを小さくします。
v3のfastifyでは、fastify-compressを使用することで実現可能です。

index.js
import fastifyCompress from "fastify-compress";

server.register(fastifyCompress, {
  encodings: ["gzip", "deflate"],
});

CLSの改善

CLSとはgoogleが提唱する「Core Web Vitals(CWV)」というウェブパフォーマンスに関する指標の一つあり、ページの安定性を示すものです。

こちらの指標を向上させるために、以下の変更を行いました。

  • 画像サイズを指定しておく
    • サイズを指定することで画像が読み込まれる前から領域を確保できる
  • loding表示中の際に表示領域を指定しておく
    • loding完了後にfooterが大きく動くことを防ぐため、height: 100vhを指定

画像の遅延読み込み

最初に読み込まれる画像以外にloading="lazy"を指定することで、一部画像の遅延読み込みを行います。遅延読み込みを行うことでページの表示速度高速化につながります。

font-display: swap

フォントの読み込みが終わるまでは代替えフォントで文字を表示します。文字を最初から表示させておくことでレイアウトシフトを予防しCLS改善に繋がります

browserslistの更新

こちらと同様の理由でbrowserslistに最新版のchromeを指定しました。こちらを指定することでBableとPostCssのトランスパイル時に サイズを最小限にしてくれます。

結果

Web Speed Hackathonでの点数は 459.75/500点という結果でした!!

lighthouseで見ても改善前と比べ大幅にパフォーマンスが上がっていますね!
ddd2a765ef1644c01f2747ef8165001a.png

300点を超えるのが目標だったので個人的には満足です。ただ採点にはややブレがあるため上振れた感は否めません(笑)

反省点

バンドルサイズの軽減・画像とフォントの最適化以外のことは余りできなかったのは心残りです。
特にmemo化やCloudFlareのCDNを利用した高速化はやってみたのですが期限までに実装できませんでした。

また、画像のリサイズ周りでVPTに何度も引っかかってしまい大幅に時間を取ってしまいました... ローカルでテストを実行する方法があったようなので、次の機会がこちらを試してみたいです

感想

今後はこちらのブログを見ながらどのような改善点があったのか確認していきたいと思います!

フロント側の速度改善方法を実践的に学ぶことが出来てとても楽しかったです!
開催してくださったCyberAgentさんありがとうございました!今まで無料デプロイを提供していたherokuにも感謝!

その他参考文献

7
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?