CSSを最適化してページの読み込み時間を高速化する方法
Post on:2020年9月30日
CSSを最適化して、ページの読み込み時間を高速化する方法を紹介します。
シンプルなCSSのファイルをはじめ、大規模プロジェクトで使用されるCSSまで、すべてのCSSに効果があるテクニックです。
Optimizing CSS for faster page loads
by Tomas Pustelnik
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
はじめに
先日、私は自分のWebサイトの読み込み時間を改善することにしました。すでにかなり高速にロードされていましたが、まだ改善の余地があり、CSSの読み込みがその原因の1つであることが分かっていました。
そのプロセスを順を追って解説し、読み込み時間を改善する方法を紹介します。
読み込みに時間がかかるのはなぜか?
「時は金なり」このことわざは、Webページの読み込み時間に特に当てはまります。ページの読み込み時間は、利益に直接影響します。人々は遅いオンラインショップよりも、速いオンラインショップで購入する可能性が高くなります。
調査によると、スマホサイトでは何百万もの改善による0.1ミリ秒の時間短縮で、コンバージョンが10.1%増加し、注文額が1.9%増加しました。
読み込み時間の改善は、多額の利益に繋がる可能性があります。
ですので、収益性の高いビジネスを構築したいのであれば、ページの読み込み時間を過小評価しないでください。
※このような調査例は他にも多数あります。上記の例は、私が見つけた最新のものを紹介しただけです。
CSSは読み込み時間にどのように影響しますか
CSSがWebページの読み込み時間にどのように影響するかを確認するには、まずブラウザがHTMLドキュメントをWebページに変換する方法を知る必要があります。
まず、HTMLドキュメントをダウンロードして解析し、DOM(Document Object Model)を作成する必要があります。外部リソース(CSS、JavaScript、画像など)を検出すると、ダウンロードの優先順位を割り当てて、ダウンロードを開始します。優先順位はページをレンダリングするために重要なリソース(メインのスタイルシートやJavaScriptファイル)もあれば、それほど重要ではないリソース(画像や他のメディアタイプのスタイルシートなど)もあるため、重要です。
HTTP/1.1には、1ドメインあたりの接続数にも厳しい制限があります(正確な数はブラウザに依存しますが、最近の通常は6です)。そのため、1つのドメインから大量のリソースをダウンロードする場合、優先度の高いリソースがダウンロードを終えるまで、それ以外のリソースはキューで待機する必要があります。したがって、HTTP/1.1を使用する場合は、リクエストの数を少なくしてください。HTTP/2にはこの制限はありませんが、今のところすべてのサイトがHTTP/2を使用しているわけではありません。
CSSの場合、CSSOM(CSS Object Model)を作成するためにはスタイルシートが必要となるため、通常はこの優先度が高くなります。Webページを表示するためには、ブラウザはDOMとCSSOMの両方を構築する必要があります。これらがないと、ブラウザは画面上のピクセルをレンダリングすることができません。その理由は、スタイルがページの外観を定義するものであり、スタイルなしでページをレンダリングすることは、処理能力とユーザーエクスペリエンスが低下するからです。
ブラウザがDOMとCSSOMの両方を利用できるようになって始めて、それら2つを組み合わせてレンダーツリーを作成し、画面のレンダリングを開始することができます。つまり、CSSはダウンロードされず、ページはレンダリングされません。
ご覧のように、CSSはWebページの読み込み時間に大きな影響を与えます。CSSについて語るとき、Webページの読み込み時間に影響を与える基本的なエリアが2つあります。
- CSSファイルのサイズとページ上のCSSの合計量(ファイル数)。CSSファイルが大きすぎると、ダウンロードに時間がかかるため、ページ全体のレンダリングに時間がかかります(大きなCSSファイルがダウンロードされるのを待たなければなりません)。
- CSSをいつ、どのように開始してダウンロードするか。できるだけ早くスタイルをダウンロードしたいと思います。
どのように改善できるかを詳しく見てみましょう。
スタイルシートのファイルサイズを制限する
要約: 可能な限り最新のコードを使用するようにツールを正しく設定してください。
読み込み時間を速くしたい場合は、CSSファイルを小さくすることは良いアイデアです。最近では古いブラウザへのフォールバックやその他の機能強化のために、ビルド時にCSSを修正するツール(PostCSSなど)を使用するのが一般的です。
最終的に、コードで不要な肥大化がないか確認することをお勧めします。特に複数のプラグインでPostCSSを使用している場合です。私の場合、CSS変数にフォールバックが生成され、古いflexbox構文のプレフィックスがついたCSSがありました。これはほとんど影響のない些細な問題のように思うかもしれませんが、私のような小さなCSSファイルでは、結果として約3Kbの節約になりました。これは、少ない作業量での大きな改善だと思います。また、大規模なCSSでは、さらに大きな影響を与える可能性があります。
1 2 |
old index.css: 12.5kB (without GZip) new index.css: 9.2kB (without GZip, ~26.4% smaller) |
私がしなければならなかったのは、Autoprefixerやその他の同様のツールで使用されるbrowserslistの設定をアップデートして、特定のブラウザのバージョンに合わせて生成されたコードをターゲットにするために使用するものです。PostCSSの設定も少しアップデートしました。また、余分なスペースを節約するために、メディアクエリを凍結するプラグインも追加しました。
私の行った設定は、下記の通りです。
クリティカルCSSを使用する
ということで、CSSファイルを縮小しましたが、それでもダウンロードする必要はあります。ネットワークリクエストを減らすことで、Webページの読み込み時間を短縮することができます。そして、最高のネットワークリクエストとは、まったくリクエストがないことです。HTMLに直接スタイルをインライン化することで、外部スタイルシートをダウンロードする必要がなくなり、読み込み時間を節約できます。
もちろん、すべてのWebページにさきほどの9Kbのスタイルシートすべてを含めることは効果的ではありません。そのため、スクロールせずに見える部分、ページの折り目より上の部分をレンダリングするのに必要なスタイルだけを含ませ、残りのスタイルは遅延ロードさせます。そうすることで、他のページはブラウザのキャッシュを利用して、Webページの読み込みを高速化できます。ページのレンダリングに不可欠なスタイルを含めるため、このテクニックはクリティカルCSSと呼ばれています。
クリティカルCSS = 折り目より上のスタイル
幸いなことに、HTMLに含めるべきスタイルを決める必要はありません。Addy OsmaniのCriticalのように、いくつかのツールが決めてくれます。このテクニックは、妥協の産物であることを心に留めておいてください。このテクニックはページを読み込む際のリクエストを1つ減らすことができますが、各ページが大きくなるため(結果としてダウンロードに時間がかかる)、何を含めるかとCSSのサイズとの間で適切なバランスを見つける必要があります。そのため、あなたのサイトで適切な設定を見つけるために、いろいろ試して結果を測定する必要があります。
遅延読み込みのスタイルシート
クリティカルCSSを使用したので、今度はページのレンダリングをブロックしないようにスタイルシートを遅延読み込みしたいと思います。古いブラウザをサポートする必要がない限り、最近の解決策は、スタイルシートに使用する通常のlinkタグを使用しますが、異なるmediaタイプと少しのJavaScriptを使用します。このテクニックはFilament Groupのブログ記事で詳しく説明されています。
下記は、その記事からのCSSを遅延読み込みさせるためのスニペットですが、私は記事全体を読むことをお勧めします。
1 |
<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'"> |
注: 上記のクリティカルパッケージを使用すると、スタイルシートが自動的に遅延読み込みされるように変換されます。
JavaScriptが無効な時用にフォールバックを含めることもできます。これにより、スタイルは正常に読み込まれ、ユーザーエクスペリエンスに悪影響を与えるようなスタイルのないコンテンツを回避できます。
1 2 3 4 |
<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'"> <noscript> <link rel="stylesheet" href="/path/to/my.css" media="screen"> </noscript> |
下記のウォーターフォール図では、クリティカルCSSを含むページがすぐにレンダリングを開始し(ブラウザのメインスレッドの行にあるグラフの紫の部分)、CSSファイルを最初にダウンロードする必要がある古いバージョンと比較して、はるかに速くインタラクティブになっていることが分かります。
クリティカルCSSがないページのウォーターフォール図
クリティカルCSSがあるページのウォーターフォール図
スタイルシートにコード分割を使用する
モダンブラウザに必要なプロパティを備えたCSSがあり、クリティカルCSSを使って残りを遅延読み込みさせました。しかし、もう少しCSSのファイルサイズを減らすことができます。
ChromeのデベロッパーツールにCoverageというツールがあります。Coverageはページに使用されているCSSやJavaScriptファイルのどの部分が使用されているかを表示してくれます。デベロッパーツールを開き、Ctrl+Shift+pを押してコマンドパレットを開き、「Coverage」と入力します。「Show Coverage」を選択すると、Coverageパネルが表示されるので、ページをリロードします。
Coverageパネル
Coverageパネル
Coverageパネルで確認してみると、私のCSSコードの45.4%がページで使用されていませんでした。また、別のページをチェックしてみると、さらに多く、53.6%が使用されていませんでした。これは大量の不要なコードです。この数字は大規模なレガシーアプリでは、さらに大きくなる可能性があります。
JavaScriptを使用する際に、コードを分割して複数の小さなファイルを作成することがよくあります。ページの読み込み時に大きな1つのJavaScriptファイルを取得する代わりに、必要な時に小さなファイルをダウンロードさせます。CSSにも同様のアプローチを使用できます。
CSSは、3つの方法で分割することができます。
1. メディアクエリに基づいてCSSを分割する
この方法は、メディアクエリに基づいて大きなCSSを小さなスタイルシートに分割し(PostCSSにはそのためのプラグインがあります)、HTMLでそれらのスタイルシートを参照します。
1 2 3 |
<link rel="stylesheet" href="index.css" media="all" /> <link rel="stylesheet" href="mobile.css" media="(max-width:44.9375rem)" /> <link rel="stylesheet" href="table.css" media="(min-width: 45rem)" /> |
このアプローチは、クリティカルCSSとスタイルシートの遅延読み込みを使用する場合にはあまり意味がないことに注意してください。ブラウザは使用されるメディアクエリに関係なく、すべてのスタイルシートをダウンロードします。ダウンロードに優先順位をつけるためにのみmedia属性を使用します。つまり、基本的にはアクティブなメディアクエリに対して優先度の高いCSSをダウンロードし、残りのスタイルシートを遅延読み込みします。
2. ページベースのコード分割
2つ目のアプローチは、各ページに個別のCSSを使用することです。上記で見たように、さまざまなページに未使用のスタイルがたくさんあります。それらの未使用のスタイルを削除して、特定のページに必要なスタイルだけを使用できれば、それは素晴らしいことです。私はこれがベストだと思います。悲しいことに、これを行うツールは見つかりませんでした。1つの大きなCSSファイルの中から、そのコンテンツに基づいて各ページの小さなバンドルを生成します。
簡単そうなので、試しにこのようなことを実行できるnodeスクリプトを作成することにしました。CSS Splitと呼ばれるもので、静的サイトジェネレーター(私はEleventyを使用しています)で構築されたサイトに最適です。未使用のスタイルを削除するためにPurgeCSSを使用しているので、HTML以外のファイルでも動作するはずです(ドキュメントによると)。HTML以外のテストはしていないので、この方法で使用する場合は、結果を再確認してください。
この方法を使用して、リクエストされるCSSのファイルサイズを50%近く減らすことができました。以下は、クリティカルCSSとページベースのコード分割を実装した後の統計です。
1 2 3 |
single index.css for all pages: 9.2kB (without GZip) CSS file for homepage: 5.4kB (without GZip) CSS file for projects: 4.4kB (without GZip) |
Homepageのファイルサイズ
Projectsのファイルサイズ
未使用のスタイルがまだ残っていることが分かります。Coverageには、ホバーやフォーカスの状態やクエリは含まれていないため、これは問題ありません。未使用のバイト数が0になることはまずありません。
3. コンポーネントベースのコード分割
3つ目のアプローチは、Harry Robertsからヒントをもらいました。コンポーネント単位でCSSを分割し、ページで使用するコンポーネント(ヘッダ・フッタ・記事など)のCSSのみを段階的に読み込むようにすることもできます。この巧妙なテクニックは彼の記事で詳しく読むことができます。私がここで取り上げているテクニックは、記事の最後のセクションで説明されています。ここでは説明しません(うまく書けませんでした)が、CSSネットワークのパフォーマンスを向上させるための素晴らしい情報が満載です。
このテクニックを使用して、現在の方法と比較してどれほどうまく機能するか確認していませんが、私のTODOリストにあります。今後の記事をお楽しみに。
まとめ
私のサイトはかなりシンプルで改善の余地はあまりありませんが、ここで解説したテクニックを使用することで、Webページの初期読み込みを高速化し、アセットの合計サイズを小さくすることができました。どのようなWebページでも同じプロセスを使用することで、読み込みのパフォーマンスを向上させることができます。大規模なプロジェクトではおそらくより良い結果が得られるでしょう。
以下に、アップデート後の最終的な結果を示します。
グラフはページの何パーセントがいつレンダリングされたかを示しています。これらのテストは低速の3G接続で実行させたもので、ページの読み込みには非常に時間がかかっています。
Homepageの最終比較
Projectsの最終比較
記事の最終比較
記事を読んでいただきありがとうございます。
記事をより良いものにするための提案やアイデアがあれば、あるいは単に気に入っていただけたら、Twitterで気軽にシェアしたり、議論したりしてください。
sponsors