「蔦屋書店ポータル」トップページの表示速度ボトルネック研究
スライダーと固定ヘッダーによるレイアウトシフト、配信終了したWebフォントのCSS読み込み、5種類のサードパーティタグなどのボトルネックが観測され、解消シミュレーションではLighthouseスコアが73から最大100まで変化する結果が得られました。Core Web Vitalsの大幅な改善が期待できます。
蔦屋書店の公式ポータルサイトです。蔦屋書店の店舗一覧、店舗を横断したイベント検索、オンラインショップへの入口をまとめており、コンシェルジュが選んだ商品やイベント、特集記事を通して上質なライフスタイルを提案しています。モバイル環境での表示速度について、どのような要素がボトルネックとなっているのかを研究するため、解消シミュレーションを実施しました。
Core Web Vitalsにつながる指標の改善ポテンシャル
観測されたボトルネックを仮に解消した場合、Lighthouse スコアは以下のような変化を示しました。
| 観測時点 | 解消シミュレーション後 |
|---|---|
![]() | ![]() |
| 指標 | 観測時点 | 解消シミュレーション後 | 変化量 |
|---|---|---|---|
総合スコア | 73 | 100 | +27 |
LCP | 1.4秒 | 0.1秒 | -1.3秒 |
FCP | 0.7秒 | 0.1秒 | -0.6秒 |
SI | 4.8秒 | 0.6秒 | -4.2秒 |
TBT | 0ms | 0ms | 変化なし |
CLS | 0.712 | 0.000 | -0.712 |
総合スコア は73から100へ、SI(Speed Index = ビューの視覚的な表示進捗の速さ)は4.8秒から0.6秒へと変化するシミュレーション結果が得られました。観測時点で最も大きくスコアを押し下げていたのは CLS(Cumulative Layout Shift = ページ読み込み中のレイアウトのずれ)で、Googleの「良好」の基準である0.1の7倍を超える0.712でした。これが0.000へと変化しています。LCP(Largest Contentful Paint = ページの主要コンテンツが表示されるまでの時間)は1.4秒から0.1秒へ、FCP(First Contentful Paint = 最初のコンテンツが表示されるまでの時間)は0.7秒から0.1秒へと変化しました。
この研究では、記録したページを回線の遅延なし、CPUの速度制限なしの条件で再生して計測しています。そのため TBT(Total Blocking Time = メインスレッドのブロック時間)は観測時点から0msで、LCP や FCP はPageSpeed Insightsで見る値よりかなり小さく出ます。たとえば解消シミュレーション後の LCP 0.1秒は、HTMLのサーバー応答時間(約1.1秒)すら下回る推定値です。本記事では数値そのものよりも、指標の差と、どのボトルネックで値が動いたかに注目しています。
読み込みプロセスの変化を動画で体験
観測時点とボトルネック解消シミュレーション後のページ読み込みを並べると、体感的にも明確な違いが見て取れます。動画は縦に長いページ全体を3列に並べて表示しています。
| 動画の計測条件での値 | 観測時点 | 解消シミュレーション後 | 変化量 |
|---|---|---|---|
| 転送量 | 3.00MB | 0.61MB | -2.39MB |
読み込み完了(onload) | 9.07秒 | 1.67秒 | -7.40秒 |
サードパーティータグの影響
本研究ではまず、サードパーティータグを段階的に除去することで、タグ全体が表示速度に与えている影響を観測しました。あわせて、タグ由来のノイズを取り除くことで、サイト自体のボトルネックを観察しやすくする狙いもあります。タグを完全に除去することは現実的ではありませんが、最適化によってどこまでの改善ポテンシャルがあるかを把握する材料としてご覧ください。
本セクションは「サードパーティータグがページスピードに影響を与えている」という現実を数値で示すとともに、それらを最適化することでどれだけのスピード改善ポテンシャルがあるかを示唆するものです。

オリジナルページの全122リソースのうち、サイト固有のリソースは88件(約7割)、サードパーティタグ由来のリソースは34件(約3割)でした。jQueryやスライダーのライブラリは自社ドメインから配信されており、公開CDNは含まれていません。ページが読み込むJavaScript約2.73MBのうち、約1.27MBが googletagmanager.com からのものでした。
HTMLから直接読み込まれているタグ
| タグ名 | 種別 |
|---|---|
Instagramフィード(Facebook Graph API の呼び出し) | SNS連携(インラインスクリプトから呼び出し) |
Google Tag Manager(GTM-WKLKCL2) | タグマネージャー(広告用) |
Google Analytics 4(gtag.js、3プロパティ) | アクセス解析 |
Google Tag Manager経由で読み込まれているタグ
| タグ名 | 種別 |
|---|---|
Facebook Pixel | 広告計測 |
Microsoft Clarity(Bingとの同期を含む) | ヒートマップ・セッション録画 |
Google Ads | 広告(コンバージョン・リマーケティング。除去は Google Tag Manager と一体) |
除去シミュレーションの結果
| 除去段階 | 総合スコア | LCP | FCP | SI |
|---|---|---|---|---|
| 観測時点(タグあり) | 73 | 1.4秒 | 0.7秒 | 4.8秒 |
| Instagramフィード除去 | 75 | 1.3秒 | 0.4秒 | 3.6秒 |
Facebook Pixel 除去 | 76 | 0.9秒 | 0.4秒 | 3.4秒 |
Microsoft Clarity 除去 | 76 | 0.7秒 | 0.4秒 | 3.2秒 |
Google Tag Manager(Google Ads を含む)除去 | 76 | 0.6秒 | 0.4秒 | 3.2秒 |
Google Analytics 4 除去 | 76 | 0.4秒 | 0.4秒 | 3.1秒 |
サードパーティータグを全て除去した状態では、総合スコア は73から76へ、LCP は1.4秒から0.4秒へ、SI は4.8秒から3.1秒へと変化する結果が得られました。これはあくまで上限値であり、実際にはこの一部しか実現できないとしても、サードパーティータグの最適化には無視できない改善ポテンシャルがあることが読み取れます。総合スコア の変化が小さいのは、この時点では CLS 0.712によってスコアの大半が押し下げられていたためです。
最初に除去したInstagramフィードは、記録時にはアクセストークンの失効で表示されておらず、APIはエラーを返していました。それでもリクエストは計測のたびに約1.6〜8.4秒にわたって接続を占有しており、除去すると SI が約1.1秒短縮しています。表示されていないウィジェットでも、読み込み中の帯域と接続を通じてページ全体の表示に影響していたことが分かります。
サイト固有のボトルネック
サードパーティータグの影響を切り離した状態を起点として、サイト固有のボトルネックを調査しました。本研究ではサードパーティータグを含む全34件のボトルネック仮説を検証しました。その中から、特に影響の大きかった3件を紹介します。
タグ除去後の CLS 0.712は、モバイル表示(幅412px)で起きた2回のレイアウトシフトの合計でした。1件目と2件目は、そのそれぞれの原因です。
ボトルネック1: スライダーの高さがJavaScriptの初期化まで決まらない
観察された状況
ファーストビューのスライダーには、jQueryプラグインの slick が使われていました。初期化前の状態では、スライド画像に position: absolute が指定されていたため、各スライドが高さを持たず、スライダー全体の高さはほぼ0でした。DOMの構築後に slick が初期化されると、スライドの最小の高さやページ送りのドット領域の余白が適用され、スライダーは約450pxへ一気に広がります。その下にあるEVENTセクションは435px押し下げられ、この1回のシフトだけで CLS に0.476が加算されていました。
解消シミュレーションの方法
slick が初期化済みの要素に付ける slick-initialized クラスがまだ付いていない状態に限って、初期化後と同じ寸法をCSSで与えました。スマートフォンでは1枚表示、PCでは2枚表示という初期化後のレイアウトも、そのまま初期状態で再現しています。
シミュレーション結果
| 指標 | 解消前 | 解消後 | 変化量 |
|---|---|---|---|
総合スコア | 76 | 87 | +11 |
CLS | 0.712 | 0.236 | -0.476 |
LCP | 0.4秒 | 0.5秒 | +0.1秒 |
1回目のシフトが消え、CLS は0.712から0.236へ、総合スコア は76から87へと変化する結果が得られました。LCP の0.1秒の増加は、次の解消シミュレーションで元の水準に戻っており、計測の揺らぎの範囲と考えられます。JavaScriptが動くまで高さを持たないスライダーが、このページの CLS の最大の要因であったことが、このシミュレーション結果から読み取れます。
ボトルネック2: 固定ヘッダーの余白がJavaScriptで後から設定される
観察された状況
スマートフォン用のヘッダーは position: fixed で画面上部に固定されており、通常のレイアウトの流れから外れています。その高さ分の余白(194px)を、DOMの構築後にjQueryで main 要素の padding-top として設定していました。JavaScriptが動くまでは余白が0のため、実行された瞬間にスライダーを含むページ全体が194px下にずれ、CLS に0.236が加算されていました。
解消シミュレーションの方法
同じ余白を、実際のヘッダーの高さ(スマートフォン194px、PC 154px)に合わせてCSSで最初から指定しました。既存のJavaScriptはスクロール時のヘッダーの格納処理と共有されていたため残しており、同じ値を再設定するだけの状態になっています。
シミュレーション結果
| 指標 | 解消前 | 解消後 | 変化量 |
|---|---|---|---|
総合スコア | 87 | 99 | +12 |
CLS | 0.236 | 0.000 | -0.236 |
LCP | 0.5秒 | 0.4秒 | -0.1秒 |
レイアウトシフトは0件となり、CLS は0.000、総合スコア は87から99へと変化する結果が得られました。ボトルネック1とあわせると、CLS は0.712から0.000へ、総合スコア は76から99へと変化しています。2件とも「最終的な寸法をJavaScriptが後から決める」構造から生じており、この構造がページの 総合スコア を23ポイント押し下げていたことが読み取れます。
ボトルネック3: 配信が終了したWebフォントのCSSが描画を止めている
観察された状況
本文の font-family には「Noto Sans Japanese」が指定され、Google Fontsの Early Access版(fonts.gstatic.com/ea/...)をCSSから直接参照していました。Early Accessはすでに配信が終了しており、フォントファイル6件はすべて404を返していました。実際の表示は、もともとフォールバックの sans-serif です。
さらに <head> では、同じくEarly Access版の「Noto Sans SC」のCSS(fonts.googleapis.com/earlyaccess/notosanssc.css)を読み込んでいました。別ドメインから配信されるレンダリングをブロックするCSS(読み込みが完了するまでページの描画が停止するリソース)で、約7,300行・909件の @font-face を含みます。一方、このフォントを使う要素はページに1つもありませんでした。
解消シミュレーションの方法
<head> の notosanssc.css の読み込みと、本文フォント(Early Access版)の @font-face 3件を削除しました。body の font-family の指定はそのまま残しており、フォールバックの sans-serif で表示される状態は変わりません。見た目は変わらないシミュレーションです。
シミュレーション結果
| 指標 | 解消前 | 解消後 | 変化量 |
|---|---|---|---|
総合スコア | 99 | 100 | +1 |
FCP | 0.4秒 | 0.1秒 | -0.3秒 |
LCP | 0.4秒 | 0.1秒 | -0.3秒 |
SI | 3.1秒 | 0.7秒 | -2.4秒 |
SI が3.1秒から0.7秒へ、FCP と LCP がいずれも0.4秒から0.1秒へと変化する結果が得られました。再計測でも同じ傾向でした。描画を始める前に別ドメインへの新しい接続とCSSの取得・解析が必要だった状態から、描画に必要なリソースが自社ドメインのものだけになったためです。表示には一切使われていないフォントの読み込みが、SI の大部分を占めるボトルネックであったことが、このシミュレーション結果から読み取れます。CLS には影響していなかったものの、SI の変化幅は本研究のボトルネックの中で最大でした。
まとめ
蔦屋書店ポータルのトップページでは、観測時点の 総合スコア が73でした。TBT は0msでしたが、CLS が0.712と大きく、SI も4.8秒かかっていました。
観測されたボトルネックとその影響は次のように整理できます。
- サードパーティータグ(5種類・34リソース): 除去によって
LCPが1.4秒から0.4秒へ、SIが4.8秒から3.1秒へ変化しました。表示されていないInstagramフィードのAPI呼び出しも、SIに約1.1秒の影響を与えていました。 - スライダーの高さがJavaScriptの初期化まで決まらない: 初期化前の寸法をCSSで与えたシミュレーションでは、
CLSが0.712から0.236へ、総合スコアが76から87へ変化しました。 - 固定ヘッダーの余白がJavaScriptで後から設定される: 同じ余白をCSSで指定したシミュレーションでは、
CLSが0.000に、総合スコアが99へ変化しました。 - 配信が終了したWebフォントのCSS: 使われていない別ドメインのCSSの読み込みをなくすシミュレーションで、
SIが3.1秒から0.7秒へ、FCPとLCPが0.4秒から0.1秒へ変化しました。
全ボトルネックの解消シミュレーションを重ねた結果、総合スコア は73から100へ、SI は4.8秒から0.6秒へと変化しています。このページでは、JavaScriptが後から寸法を決めるレイアウトと、役目を終えたまま残っていたWebフォントの読み込みという、いずれもサイトの見た目を変えずに解消できるボトルネックが、スコアの大半を左右していたことが分かります。
一方、全ての解消シミュレーションを終えた後も、HTMLのサーバー応答時間(約1.1秒)が残っていました。HTMLはCDNでキャッシュされず、毎回オリジンサーバーで生成されています。最終状態で実際に観測された FCP・LCP(約1.15秒)の約97%をこの応答待ちが占めており、サーバー側の処理であるため本研究のシミュレーションの範囲外ですが、このサイトに残る最大のボトルネックとして観測されています。

