Core Web Vitals に対応するため、各サイトの改善活動を実施しました

Core Web Vitals に対応するため、各サイトの改善活動を実施しました

アプリケーションソリューショングループの古川です。リクルートの各サイトで実際に運用されているサービスの Core Web Vitals を改善する活動をしていました。

今回はリクルート社内であったいくつかのサービスで Core Web Vitals の改善活動を行ったので、それの結果についていくつか報告します。基本的に改善活動をやってきて見えたこと、それぞれの改善ポイントを紹介できると幸いです。

リクルート内には有名なアプリケーションもこれから作られるような新規のサービスもあわせて、数百個のサービスが存在し、それの一つ一つを問い合わせをベースにパフォーマンス改善をしつつ、個々のサービスのどの場所で指摘がされたのかについて解説します。

  • ホットペッパービューティーコスメ
  • ホットペッパービューティー
  • TOWNWORK

個人がやったのはアセスメントと方針を打ち出したところで、基本的には、各部署のメンバーが中心となって一緒に改善を実施してました。
 

『ホットペッパービューティーコスメ』

AMP を利用するものの AMP Cache には載せず、 外部の CDN で高速化しているサービスです。 実際私も開発に関わっており、以下の記事で私も含めていろいろな目線で語っています。

https://codezine.jp/article/detail/12700

さて、実際蓋を開けてみると、大部分はパスしていたものの、トップページといくつかの詳細ページには Largest Contentful Paint に時間がかかっているという問題が有りました (3398ms) 。

トップページの Core Web Vitals 計測 (Lab)

これには Lighthouse や Page Speed Insights を使って解析したところ、いくつかの原因が有りました。

  • 画像がたくさんあるサイトだが、最新のフォーマットが使えていない
  • Web Font をダウンロードしている
  • サーバサイド (CDN) からレスポンスに時間がかかっている

それぞれの問題をどう対処したかについてもお話します。

画像がたくさんあるが最新のフォーマットが使えていない

AMP Cache に載せずに自分たちで選定した画像配信サーバを使っていたのですが、その画像配信サーバは webp に対応しているものの、 webp 非対応のブラウザに対して、自動で fallback する仕組みがなく、結局 jpg 等の旧来のフォーマットのものしか使えていませんでした。

それなら picture タグで最適化を… と思ったのですが、 AMP の amp-img は picture タグに対応していません。

https://github.com/ampproject/amphtml/issues/22430

ここは Fastly 製の Image Optimizer を使って、現在では webp にも fallback にも対応し、最適化しています。

Web Font をダウンロードしている

日本語の Web Font をまるっとダウンロードしていましたが、シンプルに Web Font のダウンロードをやめるようにしました。もともと Windows ユーザーがシステムフォントとして使っているデフォルトフォントが当サイトのイメージに合わないのではないかというところから指定されていたフォントでしたが、PCデバイスよりもスマートフォンで見ているユーザーの方が多いことと、デフォルトフォントだとしてもそこまでの違和感を感じないというプロダクトメンバーが半数以上いたため、交渉の末、まるごとやめることにしました。

サーバサイド(CDN) からレスポンスに時間がかかっている

基本的に CDN によって高速ではあるものの、最初選定していたCDNはどうやらキャッシュの浸透(適切な言葉じゃないかもしれませんが)に時間がかかる様子だったので、キャッシュの浸透を待つまでの期間内にリクエストが来てしまうとオリジンサーバまでリクエストが飛んでしまいます。また Stale-While-Revalidate (古くなったキャッシュを返している間に最新化する)な仕組みが使えず、ヒット率が低いままでした。

ここでは Fastly 社の Origin Shield と Stale-While-Revalidate を両方活用し、レスポンスの時間削減を行いました。

結果 (ラボデータ)

改善後の結果、LCPはms 改善

LCPが約 1600ms ほど改善されています。ただこれを見ているとまだできることはありそうです。特に Total Blocking Time にはやれることが多そうです。

Total Blocking Time に関しては AMP の JavaScript が重く、ロード時間に影響があることに起因しています。 IE11 対応の polyfill 等がまだ入っているのも AMP のサイズが大きい原因の一つです。そういったチューニングが行われていないことにも起因しています。 AMP の JavaScript は個々の Web Components としては軽量なものの、複数のコンポーネントを組み合わせると全体として重たくなります。

AMP の v0.js の中身

AMP は v0.js と呼ばれるコアのスクリプトを持っています。この中で Web Components の登録や AMP 内部で使われている汎用的な処理を請け負っているのですが、 fetch の polyfill や各種ブラウザの動きの吸収をする層を用意していて、そこの内容が “塵積(ちりつも)” で大きくなっています。

このあたりは AMP 側でも対応を進めており、 IE 対応を削ったり、 module に寄せたりすることでなるべくモダンな書き方に寄せようとしているようですが、まだ改善されきれていないです。

結果 (フィールドデータ)

フィールドデータでも Core Web Vitals 上は全く問題有りませんでした。

Field Data / Origin Summary ともにオールグリーン

ここまでスコアが良い場合はこれ以上の改善はCWV上は不要と言って良いでしょう。これ以上は CWV ではなく、さらに先の領域になると思っています。
 

『ホットペッパービューティー』

美容室やネイルサロン、エステサロン、リラクゼーションサロン、美容クリニックなどが検索できるおなじみのサービスです。初期のリリースから10年以上が経過しており、様々な内部的な進化が行われています。ただ10年経過したサービスにしては問題は少なかったです。

さて、実際蓋を開けてみると、サーバサイドでHTMLをレンダリングしつつ、インタラクティブなところはJavaScriptで動かしているプレーンな作りでした。一方で、10年以上運用されているため、不要なJavaScriptやCSSが多い状況でした。様々な解析ツールを一時的に入れていたものの、そのまま放置されてしまっているものも多く、リクエストが非常に過多な状況でした。

Web Vitals は LCP 以外はそこまで悪くない
トップページのリクエスト数が 285件、ロードが終わるまでのトータルの時間は10.52秒

いくつかの解析をした結果、以下の点が特に問題であることがわかりました。

  • 3rd Party へのリクエストが多い
  • 画像の読み込みに時間がかかる

他にも問題点はありそうでしたが、全てを洗い出して修正する事自体が目的ではなく、ひとまず CWV への影響を軽減させることが目的だったため、この2つを中心に進めました。

それぞれどういう問題だったかを詳しく解説します。

3rd Party へのリクエストが多い

Google Tag Manager などの Tag Manager から追加されたスクリプトが多く、そのスクリプトがさらにリクエストを送っているので、再帰的にリクエストが発火されてしまい、結果として 3rd Party へのリクエストが多くなっていました。

リクエストマップ、一つのノードがリクエスト先を表す

リクエストマップで見ると一つのノードがリクエスト先を表し、そのリクエスト先からさらにリクエストが発生していることがわかります。

LCP に 3rd Party へのリクエストが直接影響があるのかいまいちピンと来ないかもしれませんが、リクエストが過多だったり、 JavaScript をロードしてたりすると、そのタイミングで CPU を使用します(特に JavaScript の評価はメインスレッドを専有します)。LCPに関連するようなヒーローイメージも展開してレンダリングする際にCPUを使用します。両処理がCPUのリソースを奪い合ってしまう結果になり、LCPにも影響があります

そこまで多くなければ多大な影響があるわけでは有りません。しかし、上で記載した通り、 300 近いリクエストがあるとなると少しずつ影響が積り、遅くなります。

さらにこういった 3rd party script は開発者が入れてるわけではなく、マーケティングの部署だったり、サイト分析をする部署が入れていたりするケースが多いです。3rd party script は槍玉に挙げられがちですが、こういったツールによってA/Bテストを踏まえてユーザビリティを改善していたり、サイトの分析を行って使いにくそうなところを洗い出したりと、実際に効果があるので、無闇に消すこともできません。

初期のサイトは 3rd party script が少なく、ある程度の余裕がありますが、徐々に膨れ上がると逼迫して、遅くなります。これを予防するために、ある程度効果を鑑みて、ファイルサイズやリクエスト数をもとに制限をかけるというアイデアがあります。例えばある 3rd party script を入れた場合、分析が可能になる、その分析を入れればユーザビリティの一助になります。ただし闇雲に入れるのではなく、サイトのパフォーマンスがどれだけ遅くなるかを鑑みた上で入れるというアイデアです。これは予算の考え方と似ています。「予算をどれだけ費消するか」と「効果がどれだけあるか」を考えて入れる必要があります。このアイデアのことを Performance Budget といいます。

まだ本施策については終わっていません。開発メンバーが関連部署との調整を実施しています。使っているものや、有用なものを見分けて残す・残さないの議論をして連携して地道に削る活動をしています。時間のかかる作業なので、すぐには効果が出せませんが、マーケティング部署や分析といった関連部署にも「Performance Budget」の考え方を浸透させつつ、改善しています

画像の読み込みに時間がかかる

ホットペッパービューティーは縦に長いサイトだったので、すべての画像を一度にロードしようとすると遅くなってしまう懸念が有り、遅延読み込み(loading=lazy をimgタグに属性として追加する)を可能にすることで画像の読み込み回数を減らす施策を行いました。

表示が縦に長い上に画像が多い、遅延読み込みに変更することで改善

この他にも画像がデザインデータから適切にエクスポートされていなかったり、リサイズが甘かったりといろいろ改善点は有りましたが、一通り地道に手を入れて改善をしていきました。

結果 (ラボデータ)

3048ms から 2886ms に削減

大幅な削減にはまだ時間がかかりますが、LCPを 160ms ほどラボデータで削減しました。またJSを削ったことで Total Blocking Time も多少改善されています。

結果 (フィールドデータ)

フィールドデータではほぼ問題がなくなりました。徐々に改善を進めていった結果、LCPに関しては2.3秒で見えるようになりました。この状態で言えば SEO 上ランキングに影響がある懸念は少ないでしょう。

フィールドデータの結果(CWVはすべてグリーンに)

 

『TOWNWORK』

アルバイト検索をメインとする仕事検索のためのアプリケーションです。実際には何年か前に改善活動を進めていたため、初期リリースからかなり時間が経過しているにも関わらず、パフォーマンスはかなり維持されていました。

https://codezine.jp/article/detail/11445

特に何もしなくても CWV の影響を受けるような事は無さそうだったのですが、実際に見てみると LCP, FID, CLS には影響はなかったのですが、FCP (First Contentful Paint) だけが warn レベルになってました。

FCP以外は全て問題ない

FCPは LCP にも影響があるので、今は問題なくともそのうち CWV に影響が出る可能性もあります。そこで、 FCP と LCP に焦点を当てて改善を行うことにしました。

※ この改善に関してはすでに Node 学園でメイン開発者から発表済みです。
https://speakerdeck.com/recruitengineers/taunwakuniokerucore-web-vitalsgai-shan-shi-ce-tosoreniyorijian-etekitamofalse

いくつか解析をした結果、下記の箇所で問題があることがわかりました。

  • 画像が最適化されていない
  • キャッシュが効いていない
  • CSS を @import 経由でダウンロードしている箇所がある

画像が最適化されていない件は ホットペッパービューティー のものと基本同じです。画像を最適化するフローが整備されきれておらず、リサイズが必要だったり、縦長のサイトでは loading=lazy をつけることで遅延読み込みを行うようにしました。

残りの2つの問題について紹介します。

キャッシュが効いていない

静的アセットに対して、 query でタイムスタンプを仕込んであるものの、 Cache-Control の max-age が 0 になっており、ほぼキャッシュされていない状態でした。なぜこのような設定になっていたのか、詳細は不明ですが、リクルートは何度かキャッシュが原因の障害を生んだことが有り、その結果消極的な設定になっていたのではないかと予測しています。query のタイムスタンプが設定されているため、もしも事故が起きたとしても query タイムスタンプを延長すれば問題ないと検討しました。その結果、 max-age を1年に設定し直し、キャッシュを効かせるようにしました。

Cache-Control を 1年間に設定、これで cache が効くようになった

CSS を @import 経由でダウンロードしている

CSS内から外部のCSSをimportする仕組みがありますが、その機能を利用していました。 import 機能は CSS の評価中にダウンロードされるため、トータルでレンダリングの速度にもFCPにも大きく影響があります。

@import を使ってダウンロードをしている様子

思い切ってこの @import をやめて、一つの css にファイルを纏めました。これによって CSSダウンロードからレンダリングされるまでの時間の短縮を行うことができました。

@import をやめて一つのファイルに全てマージ

結果 (ラボデータ)

結果も全く問題がなくなりました。ラボデータ上 CWV の安全ライン以内になりました。画像やCSSの改善がここまで綺麗に結果としてでたことも良かったですが、そもそもこういった改善活動をする文化が根づいており、改善活動がやりやすい状況だったのも良かったです。

CWVはオールグリーン

結果 (フィールドデータ)

先程の FCP が黄色だった結果がきれいになくなり、全てグリーンを達成できました。ここまでくれば、 CWV 上で SEO のランキングに悪影響が出ることはないでしょう。

フィールドデータの結果

まとめ

リクルート内のいくつかのサイトを分析し、起きていた問題、原因、解決策を実施した結果をまとめました。実際の問題には技術的に解決できる問題もあれば、他部署のマーケティング活動とも密接に関わっている問題も有り、中々一筋縄で行かないものもありました。

この他にも数々のサイトを分析し、改善を行っています。まだ改善中のものもあるので、もしも結果が更新されたら追記しようと思います。

性能改善活動は単発の活動でやっても気がついたらデグレしていることも有り、短期的なスプリントではなく、長期的なマラソンのような活動として地道な改善が必要になります。ここで終わらずに、さらなる改善を続けます。

リクルートにおける改善活動が色んなサイトの参考になれると幸いです。

謝辞

本案件を遂行するに当たり、各部署の開発者およびマーケティング部署やデザイナーの方々と数カ月に渡って協力体制を組んでいただきました。中でも開発をサポートしていただいた、『ホットペッパービューティーコスメ』の可児さん、渡邉さん、恒川さん、小松さんと『ホットペッパービューティー』の手塚さん、辻さん、『TOWNWORK』の前田さんには多大な協力をしていただきました。

チーム全体として中長期的な活動が実施できたことに感謝いたします。