- 公開日:
高速な通販サイトのための設計と実装
- Authors
- Name
- 代表取締役 宮永邦彦
- @miyanaga
画像軽量化とWebフロントエンドのスピード改善の専門家です。Web系のIT技術大好き。
このサイトではスピード改善のリアルや、日々の技術的な気づきを共有します。
体感スピードの速い通販サイトを実現するにはどうすべきか、これまでの経験をもとに設計と実装のプラクティスを紹介する。
この記事は、新たに立ち上げるサイトや大幅なリニューアルを行うことを前提としている。既存サイトの手直しにはあまり実践的な内容ではないので、あらかじめ注意されたい。
また、最新の技術は全く紹介しない。最新情報をキャッチアップしたい方には不向きだろうが、本当に汎用的で実績のあるプラクティスだけを解説する。
通販サイトの特徴
通販サイトは複合的なサイトである。
- 読み物としての側面 まずユーザーは商品探しや情報収集を行う。
- ダイナミックな側面 在庫や価格は即座に反映することが求められる。
- パーソナルな側面 ログインしたユーザー固有の情報を扱う。
- インタラクティブな側面 条件による検索や、商品選択、注文操作を行う。
いわゆるメディアサイトでは、ユーザーは記事を読むことが主な目的であり、一度公開された記事が頻繁に変更されることはない。
ところが通販サイトは在庫や価格のような鮮度の高い情報や、個人的な情報を扱う必要がある。また、注文には能動的な操作を行なってもらう必要がある。このように必要な機能が多いため、設計の難易度が高い。
HTML の戦略はまるごとキャッシュ
まずトップページや商品情報ページの HTML は、CDN にまるごとキャッシュすることを推奨する。
商品情報や写真はそこまで頻繁に変更されない。先ほど触れたように、通販サイトはまず読み物としての側面がある。そのため HTML 全体をキャッシュし、即座に応答することで体感速度を最大限に高めることができる。
通販サイトのほとんどは、ユーザーのリクエストに応じて HTML を生成する仕組みになっている。当然ながら応答速度は遅くなり、サーバーもすぐ過負荷になる。
鮮度の高い情報・パーソナルな情報は JavaScript で提供
HTML を動的に生成するのが主流なのは、鮮度の高い情報(在庫や価格)、パーソナルな情報(ユーザー固有の情報やカートなどの状態)があるからだ。
しかしそれらの要素は、全体の一部であることが多い。そのため JavaScript により動的に取得し、画面上に反映すればよい。
まとめると全体は HTML をキャッシュしつつ、アクセントとなる部分は JavaScript を用いる戦略だ。
ローカルストレージのキャッシュ利用
パーソナルな情報は、そこまで更新頻度は高くない。ローカルストレージをキャッシュとして用い表示を速やかに行い、バックグラウンドでその情報を更新する戦略も考えられる。
後半のコンテンツは遅延読み込みする
通販サイトは販促目的で 1 ページに多数のコンテンツを盛り込むことが多い。たとえばレコメンデーションの類や、サイトマップを兼ねた巨大なフッターなどだ。したがってページは縦に長くなり、それらの処理にも CPU は消費されてしまう。
しかしユーザーがページの下部までスクロールするとは限らない。ヒートマップを見るとわかるが、むしろスクロールを進める機会は稀とさえ言える。
すなわち、長いページをすべて一度に読み込むのは投機的に損失が大きい。HTML に初めから載せるのは、ページ前半の主要な情報だけに留めて CPU をその表示に全振りする。
ページ後半の補助的な要素は、ユーザーがスクロールのそぶりを見せてから JavaScript を用いて遅延読み込みする。
かつてはスクロールイベントで読み込むという手法が主流だったが、今は交差オブザーバー(Intersection Observer) API を用いる。
前後の二分割で十分
補助的な要素を遅延読み込みするというと、コンテンツごとに細かく読み込みタイミングを制御するイメージがあるかもしれない。しかしページ表示直後の体験を最善化することが目的であるので、筆者としては前後二分割くらいで十分だと考える。
CSS の戦略と継続的なメンテナンス
CSS が速やかに読み込まれることも高速なページの条件である。しかし通販サイトは長期間に渡って運用されるため、CSS が肥大化しやすい。
不要になった CSS は削除して最低限のサイズに留めるべきだが、それを人力手動で行うのは事実上、不可能と言ってよい。足りない CSS は見たらわかるが、不要な CSS は知覚する手段がないからだ。
デザインパターンの網羅と CSS パージ
そこでデザインパターンの網羅と CSS パージを用いる。CSS パージは、HTML と CSS を機械的に照合し、不要な CSS を自動的に削除するツールだ。
通販サイトは基本的に決まった要素の組み合わせで構成される。それらをデザインパターンとして網羅しておき、定期的に CSS パージを行うことで CSS の肥大化を防ぐことができる。
デザインパターンの用意は新たな手間かもしれない。しかし上記のアプローチが CSS の肥大化を防ぐ唯一の方法であり、またその手法が確立できたら CSS の高速化にまつわる問題はほぼ解決する。取り組む価値はある。
その場限りの CSS は分ける
通販サイトには特集ページなどの販促コンテンツがある。そういった次々に作成される個別ページの CSS はデザインパターンに含めるべきではない。別の CSS ファイルとしたり、HTML 内のインラインスタイルとして記述する。
デザインパターンではあくまで、サイト全体で共通する土台となる要素を管理する。
画像のインライン展開はほどほどに
かつてはリソースファイルはできるだけひとつにまとめた方が良いというプラクティスがあった。そのため CSS ファイルに画像を Base64 エンコードしてインライン展開する手法が注目されたが、今や HTTP/2 の普及で効果が縮小したどころか、悪手ですらある。
表示高速化の大原則は、「HTML と CSS を全速力で処理すること」だ。CSS に画像データを含めて肥大化させると CSS の処理が遅れてしまう。
CSS は適度に分割
可能であれば CSS は適度に分割して、場面ごとに最低限、適切な CSS が読み込まれるようにしたい。
ただし、あまり細かく分割しても保守が面倒になる。筆者であれば例えば次のような分割を検討する。
- サイト全体・トップページ・商品一覧・商品詳細・ガイドなどフロントページの CSS
- 会員登録・ログイン・カート・注文など手続き系の CSS
- 特集など個別ページの CSS
実際のところ、大半のユーザーは商品探しの段階で離脱する。そのためフロントページの CSS はひとつにまとめる。手続きに進んだユーザーに向けた CSS や、個別ページの CSS を分けるという方針である。
JavaScript の利用を最小限に
意外に思われるかもしれないが、Web ページが遅い一番の原因は JavaScript だ。特にサードパーティタグ(スクリプト)の影響が大きい。
JavaScript は目に見えないから重さがわからない。しかし効果は派手だ。また、通販サイト構築の現場を広く見ても、JavaScript に本当に詳しい人材は少ない。そのため雑に乱用されてしまう。
極端な話、JavaScript さえ使わなければ、重いページを作るというのは逆に難しい。悪意やよほどの過失でもない限り、JavaScript を使わないページは速い。
先ほど HTML はまるごとキャッシュし、JavaScript で動的な情報を提供するという戦略を述べた。それと矛盾するように聞こえるかもしれないが、JavaScript の利用は最小限に抑えるべきというのが筆者の考えだ。
脱 jQuery
jQuery は便利でプラグインも豊富だが、それゆえ乱用の元にもなる。今や標準の JavaScript でも jQuery に匹敵する機能がいくつか備わっている。これから新たに構築するサイトでは、初めから jQuery を NG とするのはよい方策だ。
また、特集ページのように表現にこだわりたいページに限っては、jQuery を部分的に許可するのもよいだろう。
Alpine.js などの利用
jQuery で行いたいのは主に DOM 操作だ。Ajax により追加で何かを表示したり、表示の切り替えを行う用途である。しかし jQuery は DOM 操作を逐一行うので重い。複雑さが増すとそれだけパフォーマンスが悪化する。
例えば Alpine.js は Vue.js のようなリアクティブな機能を提供するが、jQuery に比べて軽量である。
JavaScript を使わない表現を検討する
そもそも、本当にどうしても JavaScript を使わないといけない文脈なのか、厳しく検討すべきだ。
たとえばカルーセルやモーダルは、CSS だけで表現することも可能だ。同じアニメーションであっても CSS によるアニメーションは、JavaScript による実装より遥かに軽い。
サードパーティタグの管理
商用 Web サイトの運用にサードパーティタグは欠かせない。
しかし、スマートフォンで Web サイトを閲覧しているとき、そのサイト本来のコンテンツとサードパーティのタグ、どちらがスマートフォンに負担をかけているかご存知だろうか。
今や多くのサイトで、本来のコンテンツの表示より、サードパーティタグの方がスマートフォンにかける負荷が高くなっている。まるで寄生生物に乗っ取られた宿主であり、どちらが主役かわからない。
サードパーティタグの徹底的な棚卸し
まずは不要なタグを削除する。長く運用しているサイトだと、いつ誰が何の目的で入れたかわからないタグがいくつもあるものだ。
ただ、不要なタグを削除するというアプローチはまず上手くいかない。タグが不要であると責任を持つことは難しいからだ。
そこで逆のアプローチを推奨したい。まずはサードパーティタグをリセットし、必要だと責任を持てるタグだけを追加する方法だ。
Google Tag Manager のコンテナはひとつに
はっきり言うと Google Tag Manager は軽くはない。そして、コンテナひとつずつのオーバーヘッドが大きい。
商用 Web サイトには多くの会社や人が関わっている。そこで Google Tag Manager のコンテナで権限分離を行い、ひとつのページに複数のコンテナを読み込んでいるケースがよく見られる。
このアプローチはパフォーマンスの観点からすると悪手である。Google Tag Manager を利用する場合、1 ページ内で利用するコンテナはひとつにまとめるべきだ。
できるだけ遅延読み込みする
サードパーティタグだが、メーカーの指示通り素直に埋め込むと、ページ表示のプロセスで大渋滞する。大渋滞の結果、コンテンツの表示という本来の処理に割り込みが入り、ページ表示が遅くなる。
そこでサードパーティタグは、利用者の責任において優先度を決め、優先度の低いものは遅延読み込みする。それにより渋滞を避け、本来のコンテンツ表示に道を開けることができる。
よく計測系のタグを遅延させると、データが狂うのではないかと不安を聞く。しかし心配はいらない。そもそも今も大渋滞の結果、計測がいつ行われるかは偶然に左右されている。別に今も正しく計測などできていないのだ。
画像の軽量化
実は画像データは、今や表示速度の主たる要因ではない。通信環境が日々進化した結果、画像データは確かに大きいが重くはない存在になった。
しかし通販サイトは画像が主役であり、大量の画像が読み込まれる。画像の軽量化は行った方がよい。
次世代画像フォーマットが正解
これからの画像軽量化は、次世代画像フォーマットに頼るのが正解だ。JPEG、PNG の軽量化はかなり工夫が必要だが、例えば WebP に変換するだけでデータは半分以下になる。
それさえ行なっておけば、この問題は解決と言ってよい。
コストダウンのために
AWS を基盤とする通販サイトは増える一方だが、AWS をはじめとする海外クラウドサービスは、データ転送量がそのままコストに反映される。データ転送量が毎月数十万円に達するサイトも珍しくないだろう。
通販サイトにおいてデータ転送量の大半を占めるのが画像データだ。したがって画像を軽量化すると、データ転送量によるコストを大幅に削減できる。
Web フォントは必要か
Web フォントは、表示速度に影響が少ないよう工夫されているが、それでも日本語フォントは重い。パフォーマンスの観点では使わない方がよい。
欧文フォントであれば軽量であり、例えばブランド感を出すために利用するのは合理的だろう。
個人的には、ユーザーは買い物に来ているのであり、通販サイトに日本語 Web フォントが別途必要という理由は滅多にないと考える。
まとめ
以上、高速な通販サイトを実現するため、主に新たに立ち上げる、あるいは大幅なリニューアルを行うサイトを前提に設計と実装のプラクティスを紹介した。
とりわけ新しい技術の話はない。基本に立ち返りスマホや PC のリソースは有限であること、ブラウザの動作には特性があることを意識してサイトを作ると、自ずとサイトは高速になる。
サイト高速化はダイエットと本当によく似ている。新しいダイエット手法やサプリを追いかけていても目的は達成できない。体の声を聞いて食事の制御と運動を愚直に続けるだけでよい。そして体重が増えてから対処するのではなく、増えないように予防することが最上の戦略である。