完全ガイド:Webサイト表示速度の改善・高速化の方法【WordPress対応】

よこのじ(@yokonoji_work)です。

Webサイトの表示速度の高速化を考えている方に向けて、私が知るすべてのことを紹介します。

  • 表示速度の測定する方法
  • 表示速度を遅くしている問題点の理解
  • 表示速度の改善方法

これらの手順を詳しく見ていきましょう。

着実に取り組んでいけば、ひとつの指標となるPageSpeed Insightsにおいて90以上のスコアを取ることは難しくありません(100点もサイトの状況によっては可能です)。

PageSpeed モバイルとパソコンのスコア

このスコアがすべてではありませんが、高いスコア=表示速度が速いことは、直帰率を下げるなどのSEOにも良い影響があります。

また、表示が遅いとユーザーはコンテンツを読まずに離脱します。良いコンテンツも見てもらわなければ意味がありませんので、売り上げなどのコンバージョンを上げる方法としても必ず取り組みましょう。

表示速度の測定と問題点の発見

ページの読み込みがたった1秒遅いと最大で20%もコンバージョン(成果)が低下するそうです。多くのユーザーは2秒以内に表示されることを期待しているので、自身のWebサイトの表示速度を知ることは重要です。

表示速度を確認するツール

PageSpeed Insights

ページ表示速度を評価してくれるGoogleのツールです。モバイル、パソコンの両表示について評価してくれます。

表示速度を向上させるための方法として、何ができていて何ができていないのかを示してくれます。提案してくれる最適化の方法に従えば、簡単に表示速度を向上させることができます。評価項目については「PageSpeed Insightsのルール」に掲載されています。

このツールが表示速度の確認における基本となります。とりあえずPageSpeed Insightsだけを使えれば間違いはありません(次章以降では、PageSpeed Insightsの使用を前提に説明していきます)。

PageSpeed Insights

 

Test My Site

スマホなどのモバイル端末からWebサイトを表示させたときの速度を評価してくれるGoogleのツールです

分析中に「標準接続(3G)でテストしています…」と表示されるとおり、3G回線での接続を想定した評価が行われます。2020 年の時点で、世界のモバイル回線の 70% が3G 以下の速度であることが予想されているそうです。3Gを想定した環境で十分な評価を獲得できれば、表示速度は問題ないでしょう。

Test My Site

 

WebPagetest

WebサイトのURL、テストロケーション、ブラウザを入力してテストを行うと、画像・CSS・jsファイルなどの読み込み順や時間を可視化してくれます。サイト読み込みの挙動を知るのにとても良いと思います。GoogleのPageSpeed Insightsでは単に改善方法を提案してくれますが、自身で問題箇所を突き詰めていけるのであれば、WebPagetestは良い選択肢です。

WebPagetest

 

GTmetrix

WebサイトのURLを入力するだけで無料で分析が可能ですが、より詳細な分析を行うための有料プランも用意されています。PayPalやTwitter、BMWなどからも信頼されているサービスのようです。

分析結果は各項目ごとに80%、100%のように達成度が示されており、対策が不十分な項目がわかりやすいです。上で紹介したWebPagetestのように、画像・CSS・jsファイルなどの読み込み順や時間の可視化も行ってくれるので、総合的な分析を行えるサイトだと思います。

GTmetrix

 

Website Grader

ページの読み込みパフォーマンスを簡潔に示してくれます。その他にも、レスポンシブ対応でモバイルに最適な表示がされているかということや、メタディスクリプションや見出しの付け方などのSEO対策として必要な要素を満たせているかを評価してくれます。メールアドレスの入力欄もありますが、入力しなくても分析を行ってくれます。

Website Grader

表示速度が遅い原因

GoogleのPageSpeed Insightsで測定すると、次のような表示速度を遅くしている20項目の原因を改善方法と合わせて提示してくれます。

  • レンダリングを妨げるリソースの除外
  • 適切なサイズの画像
  • オフスクリーン画像の遅延読み込み
  • CSS の最小化
  • JavaScript の最小化
  • 使用していない CSS の遅延読み込み
  • 効率的な画像フォーマット
  • 次世代フォーマットでの画像の配信
  • テキスト圧縮の有効化
  • 必須のドメインへの事前接続
  • サーバーの応答時間が遅い(TTFB)
  • 複数のページ リダイレクトの回避
  • キー リクエストのプリロード
  • アニメーション コンテンツでの動画フォーマットの使用
  • 過大なネットワーク ペイロードの回避
  • 静的なアセットでの効率的なキャッシュ ポリシーの使用
  • 過大な DOM サイズの回避
  • カスタム速度の記録と計測
  • JavaScript の実行にかかる時間
  • メインスレッド処理の最小化

これら20項目のすべてに必ずしも合格する必要はありません。ページのレイアウトやデザイン上の理由で合格できない場合もあるからです。その場合は、表示速度とUI/UXを総合的に判断して必要な要素を優先したら良いです。

20項目のうち、太字にしている部分は改善すべきである基礎的な項目です。そして、特に改善の効果が現れる項目ですので、優先して取り組みたいところです。これらの改善を行えば、他の項目もおのずと合格となるでしょう。

これら太字の項目について、なぜ表示スピードを遅くするのかを詳しく見てみましょう。

レンダリングブロック

レンダリングを妨げるリソースの除外

レンダリングとは、HTML・CSSコードをもとにブラウザにページを描画することです。この描画を邪魔=ブロックすることをレンダリング ブロックと言います。レンダリング ブロックが発生すると、当然ページの表示は遅くなります。

レンダリングとは?

ページの読み込みが始まると、ブラウザはHTML・CSSをパース(解析)してDOMツリーとCSSOMツリーを構築します。そして、それらを組み合わせて構築したレンダーツリーの情報を元にページを表示します。

DOMとCSSOMの構築から描画、表示の一連の工程がレンダリングとなります。

webkit-rendering-flow

このうち、レンダリング ブロックはDOM構築のためのパース時に起こります(CSSの解析が完了しなくてもレイアウトが崩れるだけです)。

DOM、CSSOMとは?

DOM(Document Object Model)とは、HTMLコードの記述内容をブラウザが解析した結果です。

解析結果であるDOMは「divタグの中にpタグとaタグという要素があり、その属性は○○で、△△というテキストが記述されている」というような情報を持っています。

dom-tree

CSSOM(CSS Object Model)とは、CSSコードの記述内容を解析した結果で、bodyのfonto-sizeは16px、.classのcolorはblueといった情報を持っています。

cssom-tree

「レンダリングブロックとは何なのか 実際にやってみた」という記事で面白い実験が行われています。その結果がこちらです。

  • CSS/JavaScriptなしのページ - レンダリングブロックされない
  • headタグ内に直接cssを埋め込む - レンダリングブロックされない
  • headタグ内で外部cssを指定する - レンダリングブロックされる
  • headタグ内に直接JavaScript処理を埋め込む - レンダリングブロックされない
    (読み込みによるブロックはないが、処理中はブロックされる
  • headタグ内で外部jsファイルを指定する - レンダリングブロックされる
  • imgタグ内で画像を表示 - レンダリングブロックされない
  • cssのbackground-imageで画像を表示 - レンダリングブロックされない

レンダリングをブロックするのは、DOM構築中(html解析中)にCSSやJavaScriptなどの外部ファイルを読み込むことと、Javascriptの実行中です。

つまり、外部ファイルの読み込みが遅かったり、scriptの実行タイミングが悪いと、それだけページの表示が遅くなるということを理解いただけたでしょうか?

 

改善方法を知る

画像の読み込み

適切なサイズの画像
オフスクリーン画像の遅延読み込み

ブログ記事には、アイキャッチ画像があって、その他コンテンツの説明のための画像が使われます。これらの画像はWebページを構成するファイルの中でもかなりのデータサイズを占めるものです。

例えば、写真素材サイトUnsplashから次の画像を見つけたとします。この写真の元サイズは6016×3384の2.7 MBです。

Unsplash 平原

@peter_oslanec – Unsplash

外部ファイルとしてCSSやJSを読み込むことはどのページでも行っていますが、”重いファイル”としてWebエンジニアを悩ましている次のようなファイルでも100~300 KB程度です。

ファイル名サイズ
bootstrap.css188 KB
bootstrap.min.css153 KB
bootstrap.js129 KB
bootstrap.min.js57 KB
jquery-3.3.1.js275 KB
jquery-3.3.1.min.js84.8 KB

Bootstrap(v4.3.1)/jQuery(v3.3.1)

2.7 MBの画像はデータサイズが大きすぎると分かりますね。600×338まで小さくすると、データサイズは55.5KBです。

また、このような大きなサイズのデータであるにもかかわらず、ページの下の方にある画像も最初にまとめて読み込むのは合理的ではないと感じませんか?

画像サイズと読み込みタイミング、これらがページの表示速度を低下させる原因だということを分かってもらえたのではないでしょうか?

 

改善方法を知る

ファイルの転送データサイズ

CSS の最小化
JavaScript の最小化
テキスト圧縮の有効化

ページを構成するHTMLコードやCSS・JSファイルは、一つずつのデータサイズは小さくても全体では大きなデータサイズになるので、ページの表示を遅くしています。

この問題を解決するひとつの方法にminify(ミニファイ)があります。これは、記述されたコードから改行やスペースといった無駄なものを取り除くことでデータサイズを小さくする手法です。

先ほど紹介した表のminと付いたファイルがminifyされたものです。ファイルの規模にもよりますが、データサイズを半分以下にできる可能性があります。

ファイル名サイズ
bootstrap.css188 KB
bootstrap.min.css153 KB
bootstrap.js129 KB
bootstrap.min.js57 KB
jquery-3.3.1.js275 KB
jquery-3.3.1.min.js84.8 KB

また、CSS・JSファイルのようなテキストデータは圧縮されていないデータです。JPEGやPNGのような既に圧縮された画像データとは違って、テキストデータには圧縮する余地があります。

こちらの表はgzipという圧縮形式を利用することで、どの程度ファイルのデータサイズを削減できるのかを表したものです。

944-gzip-css-js-gzip削減率

テキストベースのアセットのエンコードと転送サイズの最適化

この表を見ると、元のデータサイズの60~90%ほど削減、つまり最大で元の1/10にまでデータサイズを小さくできるということがわかります。圧縮したデータサイズの小さいファイルであれば、読み込みが速くなることが想像できますね。

このように、テキストデータには記述と転送時に無駄がありますので、これらがページの表示速度を遅くする原因となっています。

 

改善方法を知る

動的なページ生成

サーバーの応答時間が遅い(TTFB)

この項目は、主にWordPressで作成されたページで問題になるものです。

TTFB(Time To First Byte)は、ブラウザがWebサーバーにリクエストを送信してから、Webサーバーが最初の1バイトの応答をブラウザに返すまでの時間です。この時間が長いとページの表示が遅れることになりますので、改善を提案されるというわけです。

WordPressはサーバー側でPHPの処理によりHTMLコードが動的に生成されています。

  1. ブラウザ -> サーバーへのリクエスト
  2. サーバーでHTMLコードを生成
  3. サーバー -> ブラウザへのレスポンス

HTMLコードが最初からhtmlファイルとして用意されている静的なページであれば、2. の処理がありませんので、すぐにサーバーからファイルが送信されます。

しかし、動的なページの場合は、プログラム処理によりhtmlファイルを組み立ててからファイルを送信するので、ファイルの組み立ての時間だけ時間がかかります(その代りカテゴリごとに関連記事を変えるなどの柔軟な表示が可能なのですけどね)。

このような仕組みなので、PHPで動的にページを生成するWordPressは表示が遅いということになります。または、単にサーバーのハードウェア スペックが低い場合もあります。

なお、PageSpeed Insightsにおいては、ネットワーク遅延が差し引かれた条件で評価されますので、1.と3.は関係ありません。実動作上も1.と3.の影響は小さいので、2. に絞って対策すれば問題ありません。

 

改善方法を知る

表示速度を改善する方法

前の章で確認したページの表示速度を遅くする原因に対する改善方法を紹介します。

「レンダリングを妨げるリソースの除外」の改善

レンダリングを妨げる主な原因は次のとおりです。

  • HTML解析中にCSSの外部ファイルを読み込む
  • HTML解析中にJavascriptの外部ファイルを読み込む

これらを解決する方法にコードのインライン化があります。これは、htmlファイルにcssやjsのコードを記述する方法です(外部ファイルを作らない)。

しかし、外部ファイルを作るメリットはブラウザのキャッシュを利用できることにあります。ブラウザは一度読み込んだファイルを一定期間保持することで次回読み込み時に無駄なファイルの読み込みをなくしてページの表示を速くしています。

そのため、よほど小規模な外部ファイルでない限りは、インライン化はするべきではないと私は考えています。

そこで、外部ファイルのメリットは活かしつつレンダリング ブロックを避けるために、ファイルの読み込み方法と読み込み箇所を工夫しましょう。

 

○CSSの外部ファイル

CSSについてはページのレイアウトやデザインを決める重要な要素ですので、基本的には何もしなくて良いと思います。後に紹介する「CSS の最小化」と「テキスト圧縮の有効化」でレンダリング ブロックによる表示遅延もある程度解消されます。

ただし、Googleフォント(Google Fonts)やFontAwesomeといった、サイズは大きいのに装飾をするだけのファイルは、遅延読み込み(非同期読み込み)を検討するのも良いでしょう。

その方法は、linkタグにpreloadという属性を付ける方法です。

preloadは、dns-prefetch, preconnect, prefetch, prerenderのような、リンク先のリソースを事前に読み込む方法とは異なり、preloadの記述がある現在のページでレンダリング ブロックを発生させずに非同期で読み込む方法です。scriptの読み込みにおけるasyncやdeferのような感じで使用します。

<link rel="preload" as="style" href="https://fonts.googleapis.com/css?family=Noto+Sans+JP" crossorigin="anonymous">

as属性で読み込むリソースの種類を指定しています。また、crossorigin属性は空の場合anonymousになるのですが、明示のために記述しています(記述なしでもOKです)。

crossorigin属性は、CORS(Cross-Origin Resource Sharing)というオリジン間でのデータ共有に関する約束事に関する指定です。異なるオリジン間でデータをやり取りするにはセキュリティ上注意が必要になることもありますので、HTTP認証などの認証を求めるかどうかをanonymous/use-credentialsで指定します。

anonymous:認証情報は不要
use-credentials:認証情報を求める

オリジンとは、スキーム、ホスト、ポートを組み合わせたもののことです。

スキーム:http:// or https://
ホスト:example.com
ポート:80

さて、preloadについて注意する点としては、preloadはあくまでも非同期で読み込むための指示であることです。通常はrel属性にrel=”stylesheet”と記述することで読み込んだcssを適用しています。しかし、preloadはダウンロードするだけですので、何らかの方法で読み込んだスタイルシートを適用させる必要があります。

そこで、次のような記述を行います。

<link rel="preload" as="style" href="https://fonts.googleapis.com/css?family=Noto+Sans+JP" onload="this.rel='stylesheet'">

イベントハンドラonloadを検出して、rel=”preload”をrel=’stylesheet’に書き換えています。これにより、ページ内のリソースの読み込みが完了した時に、非同期で事前に読み込んでいたCSSを適用させることができます。

この方法では、onloadを検出するまでの時間が長いとCSSの適用が遅れ、一時的に標準フォントで表示される場合があります。なお、Chrome, Firefox, Operaではフォントのダウンロード待ちが3秒続いてはじめて標準フォントが表示されますので、それまでは文字がない状態となります。

このような感じですね(FOUT(Flash of Unstyled Text)などと呼ばれる現象です)。

17-web-font-google-onload

これを回避するには、onload(HTMLとファイル・画像などがすべて読み込み完了)までの時間を3秒未満にする方法が考えられます。しかし、すべてのリソースの読み込みを予測するのは難しいです。

その他、DOMContentLoaded(HTMLの読み込みのみ完了)を利用すればloadイベントより前にrel=’stylesheet’への書き換えを実行することができます。

<link id="link-preload" rel="preload" as="style" href="https://fonts.googleapis.com/css?family=Noto+Sans+JP">

<script>
  document.addEventListener('DOMContentLoaded', function(){
    var link = document.getElementById('link-preload')
    link.rel = "stylesheet";
  }, false);
</script>

DOMContentLoadedより前にGoogleフォントやFontAwesomeのファイルの読み込みが完了するかどうかをチェックする必要がありますし、これでもフォントのちらつきを抑える3秒未満に読み込みが完了するか分かりません。ページごとにファイル構成や読み込みデータ量が違うからです。

このように、GoogleフォントやFontAwesomeはデータが大きくて読み込みを遅くする原因ですが、その改善はかなり難しいものとなっています。

そのため、テキストについては端末に搭載の標準フォント(例えば、游ゴシック体など)を使ってファイルの読み込みをなくすのが無難です。

関連:標準フォント游ゴシック(Yu Gothic)をWebサイトで使うことを検討しました

このサイトでは、Windows:メイリオ、Mac:ヒラギノ角ゴシックを使っています(2019年3月時点)。欧文はSegoe UI、日本語はメイリオの組み合わせは、バランスの取れた組み合わせはとして支持されています。

font-family: "Segoe UI", Roboto, "Helvetica Neue", "ヒラギノ角ゴ ProN W3", "Hiragino Kaku Gothic ProN", メイリオ, Meiryo, sans-serif;

FontAwesomeは普通の方法で読み込めば良いと考えます。以降で説明するいくつか改善方法で総合的にページの表示速度を向上させれば良いからです。

 

○Javascriptの外部ファイル

JavaScriptにも非同期でファイルを読み込む方法があり、defer/asyncという属性によりその制御が可能です。

レンダリング ブロックの原因で説明した次の2つを前提知識として、属性の有無による挙動を確認してみましょう。

  • HTML解析中(パース中)の外部ファイル ダウンロードはレンダリングをブロックする
  • HTML解析中(パース中)のJavascript実行はレンダリングをブロックする

・属性なしの場合

パースが中断されるのは、ダウンロード時間+スクリプト実行の時間です。

HTMLのパースは記述コードの上から実行されます。scriptタグに属性がない場合は、scriptタグに到達したタイミングでダウンロードを行い、ダウンロード中はパースが中断されます。また、ダウンロードが完了するとすぐにスクリプトを実行しますので、ダウンロード+スクリプト実行の時間分パースが中断されます。

・defer属性の場合

非同期にてパースと並行してファイルがダウンロードされるため、パースは中断されません。スクリプトはDOMが構築されてから、DOMContentLoadedイベントのタイミングで実行されます。

DOMContentLoadedは、HTMLドキュメントの読み込みと解析が完了した時に発火し、スタイルシートや画像、サブフレームの読み込みが終わるのを待ちません。

loadは、リソースおよびその依存リソースの読み込みが終わると発生します(スタイルシートや画像などの読み込み完了を待つ)。

DOMContentLoaded – MDN

複数のscriptタグにdeferを付けた場合は上から順番にスクリプトが実行されます。

<script src=”1.js” defer></script>
<script src=”2.js” defer></script>

この場合は、1.js → 2.jsの順番にスクリプトが実行されます。

<script src=”1.js” defer></script>
<script src=”2.js”></script>

この場合は、2.js → 1.jsの順番にスクリプトが実行されます。

2.jsにはdeferが付いていないので2.jsのスクリプトはパースを中断して実行され、その後DOMが構築されてから1.jsが実行されます。

<script defer>を複数記述した場合、実行順序は保証されるでしょうか?

・async属性の場合

asyncも非同期にてパースと並行してダウンロードされるため、ダウンロード中にパースは中断されません。しかし、ダウンロード完了後すぐにスクリプトが実行されますので、パースが完了する前にスクリプトが実行されてパースを中断することがあります。パースが完了した後でのスクリプト実行であれば影響はありません。

スクリプトはloadイベントの発生までには実行されますが、DOMContentLoadedイベントの後に実行される可能性はあります。そのため、DOMContentLoadedが処理の条件になっている場合、DOMContentLoadedが検知できずに処理が実行されないという罠にハマるかもしれませんので注意が必要です。

また、複数のscriptタグにasyncを付けた場合、deferと異なり実行の順番は保証されません。実行順が重要なスクリプトの扱いには注意が必要です。

 

これらの挙動をまとめたのがこちらの図です。

deferとasync

HTML Living Standard / 4.12 Scripting

scriptタグに属性の指定がない場合(1行目)は、パースを中断してファイルのダウンロードとscriptの実行が行われています。

対して、defer(2行目)とasync(3行目)はパースと並行してダウンロードが行われています。そして、deferの場合は、パースが完了した後にスクリプトを実行するので、最もレンダリング ブロックの回避に効果的です。スクリプト実行順はコードの記述順ですので、実行順が動作に影響する場合は注意してください。

記述方法は次の通り、属性としてdeferかasyncを付けるだけです。

<script src=”sample.js” defer></script>
<script src=”sample.js” async></script>

極力早く実行する必要がある処理はasyncを付けて<head>タグ内に記述してください。

deferの場合はインライン記述と同様に</body>の直前で記述するのが良いです。</body>の直前に記述してもあまり効果がないように思えますが、インライン記述と比べると複数のファイルを並列で読み込む分速くなります。

asyncの場合もそうですが、<head>タグ内にすべてを記述するとCSSや画像などと一緒にダウンロードされるので通信回線が圧迫されて表示が遅くなる可能性がありますので、早く処理する必要がなければ</body>の直前に記述することをおすすめします。

 

WordPressの場合についても少し確認しておきましょう。

WordPressはjQueryの読み込みを標準で用意してくれていますが、読み込み位置が<head>要素になっています。当然、これではレンダリング ブロックが発生してページの読み込み速度にも影響があります。jQuery必須のプラグインもあり、jQueryを使用しないというのは難しいですから、せめてもの対応として</body>の直前でjQueryを読み込むように変更しましょう。

やることは、この3つです。

  1. wp_head()でのjQuery読み込みを削除
  2. wp_footer()でjQuery読み込む
  3. 読み込むjQueryはCDNからとする

この完成コードをfunctions.phpにまるまるコピペしてもらえればOKです。

function cdn_jquery() {
  if( !is_admin() ) {
    wp_deregister_script('jquery');
    wp_deregister_script('jquery-core');
    wp_deregister_script('jquery-migrate');

    wp_register_script('jquery-core', 'https://code.jquery.com/jquery-3.3.1.min.js', array(), '3.3.1', true);
    wp_register_script('jquery-migrate', 'https://code.jquery.com/jquery-migrate-3.0.1.min.js', array(), '3.0.1', true);
    wp_register_script('jquery', false, array('jquery-core', 'jquery-migrate'), false, true);

    wp_enqueue_script('jquery');
  }
}
add_action('wp_enqueue_scripts', 'cdn_jquery');

これで、</body>直前でjQueryを読み込むことでレンダリングブロックを回避できます。また、独自ドメインから配信されていたjQueryファイルを、CDNからの配信に変更しているのでサーバー負荷を低減できます。

1.  wp_head()でのjQuery読み込みを削除 の解説

wp_register_scriptwp_enqueue_script関数は、第5引数($in_footer)によりscriptの記述位置を指定できます。初期値ではfalseなので<head>内(wp_head()の記述位置)に記述のため、一度この登録を解除します。

wp_deregister_scriptは登録されているスクリプトを解除する関数です。この関数でjquery, jquery-core, jquery-migrateを解除しています。

wp_deregister_script('jquery');
wp_deregister_script('jquery-core');
wp_deregister_script('jquery-migrate');

これで、独自ドメイン管理のjQueryが<head>内(wp_head()の記述位置)で読み込まれることはなくなりました。

25-wp-head-footer-変更前後

2. wp_footer()でjQuery読み込む の解説

wp_register_script/wp_enqueue_script関数の第5引数($in_footer)をtrueにすることで、登録したスクリプトはwp_footer()の位置に記述されます。wp_footer()はフッター部分に記述するものですので、</body>直前にスクリプトが挿入されることとなります。

wp_register_script('jquery-core', 'CDNのURL', array(), 'VER', true);
wp_register_script('jquery-migrate', 'CDNのURL', array(), 'VER', true);
wp_register_script('jquery', false, array('jquery-core', 'jquery-migrate'), false, true);

wp_enqueue_script('jquery');

wp_register_scriptはスクリプトの登録のみで、wp_enqueue_scriptは登録済みのスクリプトコードをページに生成します。wp_enqueue_scriptで登録と生成を一緒にすることもできますが、今回はmigrateファイルの読み込みも行うため、wp_register_scriptにて”jquery”という名前でjQuery本体(jquery-core)とmigrateファイル(jquery-migrate)をセットにして生成させています。これで、jQuery本体 → migrateファイルの順で必ず読み込むことができますし、両ファイルの間に別のファイルの読み込みが入ることもありません。

第4引数($ver)には、クエリ文字を指定します。「jquery-3.3.1.min.js?ver=3.3.1」のようにファイルのバージョン管理する場合は何らかの文字列を入力してください。falseであれば指定なしです。

ここまでの対応により、</body>の直前でjQuetyが読み込まれるようになっています。

3. 読み込むjQueryはCDNからとする の解説

jQueryのCDNはGoogleを使いたいところですが、Googleにはmigrateファイルが用意されていません。そのため、jQuery公式サイトでも紹介されているStackPathでjQuery本体とmigrateを読み込むことにしました。これにはDNS Lookupの回数を減らすという意図があります。

wp_register_script('jquery-core', 'https://code.jquery.com/jquery-3.3.1.min.js', array(), '3.3.1', true);
wp_register_script('jquery-migrate', 'https://code.jquery.com/jquery-migrate-3.0.1.min.js', array(), '3.0.1', true);

これで</body>の直前で、CDNを利用してjQueryを読み込むことができるようになります。

 

原因を再確認する

「適切なサイズの画像/オフスクリーン画像の遅延読み込み」の改善

画像が表示を遅くする主な原因は、次の2つです。

  • 大きなデータサイズの画像を読み込んでいる
  • 見えない画像もアクセス時に読み込んでいる

無駄に大きくなサイズでデータ量が多い

これについては、まずは画像の大きさを小さくしてください。

コンテンツの表示領域より大きなピクセル値を持つ画像は縮小されて表示されますが、それは無駄なデータを読み込んでいるということです。

適切な画像サイズにしていれば無駄なデータを読み込む必要はなくなりますので、表示は速くなります。Windowsのペイントでも良いですし、PhotoScape Xのような写真編集ソフトを使うのも良いでしょう。

PhotoScape Xのサイズ変更

画像のデータサイズを小さくする有効な方法はもう一つあります。それは、画像の圧縮です。

画像の圧縮とは?

画像の圧縮とは、画像から不要なデータを取り除いてデータサイズを小さくすることです。圧縮前後で違いがわからない範囲で色の数を減らしたりしています。メタデータを削除したりもします。

画像のサイズを小さくする、縮小とか異なるものです。

画像圧縮はツールで簡単に行なえます(括弧内はあるjpeg画像を圧縮したときのデータ削減率です)。

最も削減率の大きいTinyJPGでは63%もデータサイズが小さくなりますが、次の画像のとおり、圧縮していても見るのに十分なクオリティを維持しています。

左:圧縮なし/右:圧縮あり

06-image-compression-圧縮前後比較

このように、人の目には違いがわからないレベルでクオリティを調整する画像の圧縮は、ページの表示速度向上のために必ず取り入れたい方法です。

 

先ほど紹介したツールを使って画像を圧縮するのも良いですが、WordPressの場合にはプラグインを使えばより簡単ですので、そのプラグインを紹介します。

画像圧縮のプラグインとしてよく知られているプラグインは次の2つです。

「Compress JPEG & PNG images」は先ほど紹介したTinyJPG/TinyPNGが提供しているWordPressプラグインです。設定・使い方は簡単です。

プラグインをインストールして有効化すると、次のような赤い表示が出てきます。

06-image-compression-登録

表示されているリンク先はアカウント登録画面です。ここでアカウント登録をして、送られてきたメールから認証完了すれば使用可能となります。

または、こちらから登録して、取得したAPI Keyを入力するのでもOKです(設定画面は英語表示なのでGoogle翻訳をしています)。

06-image-compression-登録入力

設定は特に変更をしなくても利用できますが、アップロードした画像の圧縮タイミングと圧縮をかける画像サイズは確認しておいた方が良いかもしれません。

06-image-compression-設定

私の場合はバックグラウンド(アップロード後、サーバー側で任意のタイミングで圧縮)ではなくて、アップロード時に圧縮させています。多少アップロードに時間はかかりますが、アップロード完了時に圧縮されていることが確認できるのでこの設定を選んでいます。

また、無料利用の場合アップロードできる画像は月500枚ですが、圧縮する画像サイズにチェックを入れるほど上限枚数は少なくなります(上図の場合3つのサイズで圧縮するため、1枚アップロードで3枚分消費します)。

以上の設定で新しくアップロードする画像については圧縮されるようになります。

 

既にアップロードしている画像の圧縮については、2つの方法があります。

  • 画像ごとに圧縮する方法
    メディアライブラリより対象画像を開いて「さらに詳細を編集」->「Compress」
  • 一括で圧縮する方法
    ダッシュボードの「メディア」->「Bulk Optimization」->「Start Bulk Optimization」

一括で圧縮する場合は、次の画面で「Start Bulk Optimization」ボタンを押せば圧縮が開始します。アップグレードしませんか?と聞かれるかと思いますが「No thanks, continue anyway」で無視して大丈夫です。

06-image-compression-nothankyou

以上でCompress JPEG & PNG imagesの設定と使い方は終わりです。

もう1つのプラグイン「EWWW Image Optimizer」の使い方については「EWWW Image Optimizer の設定方法と使い方」を参考にしてください。「Compress JPEG & PNG images」と「EWWW Image Optimizer」は基本的には同じ機能を持っているのでお好みで選んで良いでしょう。

メタデータとは?

画像の圧縮はメタデータも削除すると説明しましたが、メタデータとは、画像データに含まれるカメラの情報(Exif:エグジフ、イグジフ)などのことです。

Exif(Exchangeable image file format)は、次のようなデータを保持することができます。

撮影日時
撮影機器のメーカー名(製造・販売元)
撮影機器のモデル名(カメラ付き携帯電話・スマートフォンの機種名など)
画像全体の解像度
水平・垂直方向の単位あたり解像度
撮影方向
シャッター速度
絞り(F値)
ISO感度
測光モード
フラッシュの有無
露光補正ステップ値
焦点距離
色空間(カラースペース)
GPS情報 – GPS付きカメラの場合、緯度・経度・標高など。
サムネイル(160×120画素)

Exchangeable image file format – Wikipedia

Exifのデータサイズ

次のようなExifデータを持つある画像(108 KB)のExifデータを削除したところ、25 KBも削減できることが分かりました。これは無視できるものではありません。

Exifデータ
35mmフイルム換算焦点距離57 mm
Circle Of Confusion0.002 mm
DateTimeDigitizedサブ秒035
DateTimeOriginalサブ秒035
Exifバージョン0221
Field Of View35.1 deg
F値2.2
Hyperfocal Distance3.58 m
ISOスピードレート200
Lens MakeApple
Lens ModeliPhone 6s back camera 4.15mm f/2.2
Light Value5.6
Scale Factor To 35 mm Equivalent13.7
XとY解像度単位インチ
YとCの位置中央
オリジナルデータ作成日時2018:12:12 21:52:17.035
サポートフラッシュピックスバージョン0100
シャッタースピード1/20
シーンキャプチャタイプスタンダード
シーンタイプ直接撮影画像
ストロボフラッシュ未発光、オートモード
センサー方式単板式カラーセンサー
ソフトウェア12.0
デジタルズーム比率1.948453608
デジタルデータ作成日時2018:12:12 21:52:17.035
ファイル作成日時2018:12:12 21:52:17
ブライトネス1.577715434
ホワイトバランスオート
メーカーApple
レンズ情報4.150000095mm f/2.2
レンズ焦点距離4.2 mm (35 mm equivalent: 57.0 mm)
各構成要素の意味Y, Cb, Cr, –
対象領域2004 1508 2215 1325
測光モードパターン
画像の向き水平(標準)
画像入力機器モデルiPhone 6s
画像幅4032
画像幅の解像度72
画像高さ3024
画像高さの解像度72
絞り2.2
色空間sRGB
露光モード自動露出
露出プログラムノーマルプログラム
露出時間1/20
露出補正値0

CMAN 画像のexif・メタデータ等の情報確認/削除にてExifデータを確認

Exifデータ削除によるデータ削減量は、4つの方法で確認を行いました。

  1. 画像プロパティより「プロパティや個人情報を削除」->「可能なすべてのプロパティをすべて削除してコピーを作成」
  2. Webツール Syncer Exif削除ツール
  3. Webツール CMAN 画像のexif・メタデータ等の情報確認/削除
  4. フリーソフト F6 Exif

確認結果は次のとおりです。

  • 方法1:112,759 バイト(+3,827バイト)なぜか増えています
  • 方法2:83,777 バイト(-25,155バイト)
  • 方法3:104,836 バイト(-4,096バイト)
  • 方法4:104,836 バイト(-4,096バイト)

削減されるデータ量は、埋め込まれているExifデータによりますが、Exifの削除は大きな効果があるようです。最も削減できたのは、SyncerのExif削除ツールです。

 

見えない画像もアクセス時に読み込んでいる

これを改善する方法は、画像の遅延読み込み(Lazy Load)です。

画像の遅延読み込み(Lazy Load)とは、画像がある位置までスクロールしたときに画像の読み込みを行う方法です。通常は、ページを開いたときにまとめて読み込まれますが、分散的に読み込むことで最初のページ読み込みが速くなります。

実際に見たほうがどのような感じか分かりやすいので、デモページをご確認ください。

画像の遅延読み込み

このLazy Loadの実装は、WordPressであればプラグインを導入するだけで実現できます。

これらのプラグインはインストールして有効化するだけで使うことができます。

特におすすめしたいのは、一番上のUnveil Lazy Loadです。このプラグインは、プラグイン自体のファイルサイズや処理の最適化などの点をよく考えて設計されているからです(詳しくは公式ページへ)。

なお、遅延読み込みを使うと、クローラー(Google bot)は画像を認識してくれません。クローラーはソースコードを見るだけで、スクロールの操作は行わないからです。これはSEOにも影響しかねない問題です。

そこで、プラグイン → プラグインエディターより、プラグインのファイル「unveil-lazy-load/unveil-lazy-load.php」を編集しましょう。これによりGoogle botがアクセスしたときには遅延読み込みが無効となりますので、ちゃんと画像を取得してもらえます。

変更前:if(is_feed() || is_preview() || $this->is_smartphone()) return $content;
変更後:if(is_feed() || is_preview() || $this->is_smartphone() || stripos($_SERVER['HTTP_USER_AGENT'], 'Googlebot')) return $content;

WordPressではないページなどでは、つぎのライブラリを使用すれば遅延読み込みを実装できますので、参考にしてください(両プラグインはjQueryなしで実装できます)。

 

原因を再確認する

「CSS の最小化/JavaScript の最小化/テキスト圧縮の有効化」の改善

画像のデータサイズが大きいことがページの表示速度低下につながるように、HTML, CSS, JSのようなテキストデータのデータサイズも表示速度に影響します。

ここでは、次の2つの改善方法を紹介します。

  • テキストファイルの最小化
  • テキストファイルの圧縮

テキストファイルの最小化

最小化を行うのは、ミニファイ(minify)という方法です。

次のようなCSSの記述があるとします。

body{
  font-family: "Segoe UI", Roboto, "Helvetica Neue", "ヒラギノ角ゴ ProN W3", "Hiragino Kaku Gothic ProN", メイリオ, Meiryo, sans-serif;
  color: rgba(0,0,0,0.85);
}

ミニファイ(minify)とは、次のようにコードの改行やスペースを消去することです。これによりデータサイズが小さくなり、ファイル規模によっては半分以下のサイズになります。

body{font-family:"Segoe UI",Roboto,"Helvetica Neue","ヒラギノ角ゴ ProN W3","Hiragino Kaku Gothic ProN",メイリオ,Meiryo,sans-serif;color:rgba(0,0,0,.85)}

ミニファイはツールを使えば簡単に行なえます。

通常のファイルは開発用にして、公開用はミニファイするのが一般的です。もし、ミニファイしたコードを元の形に戻す場合はdirtyMarkupPretty Diffを使用してください。

WordPressの場合は、Autoptimizeというプラグインを使用すると簡単にミニファイできます。複数のファイルを一つにまとめるなどの最適化も行われるので、ぜひ試してみてください。

Autoptimizeの設定

 

テキストファイルの圧縮

ファイルを圧縮してデータ転送サイズを小さくするという方法もページの表示速度を高める良い方法です。これにはgzip圧縮という方法を利用します。

gzip(ジージップ)圧縮とは、圧縮フォーマットの1つです。html、css、jsファイルのようなテキストベースのファイルの圧縮に適しています。gzip圧縮するとファイルに.gzという拡張子が付きます。

Webページは、Webサーバーから送られたファイルをブラウザが受け取って表示させています。そのため、データサイズが大きく転送に時間がかかるファイルがあると、ページの表示は遅くなります。

gzip圧縮すると、最大で元のデータの1/10にまでデータサイズを小さくできます(60~90%削減)。これによりファイルの読み込みが速くなり、ページの表示速度が向上します。

gzip圧縮の仕組み

gzipは、繰り返し表れる文字列を代わりの文字列に置き換えることでデータサイズを縮小させています。どのようなことが行われているかのイメージとして、次の例をご覧ください(実際の圧縮操作とは異なります)。

元のデータ:hello world. hello world. hello world. hello world. hello world.
圧縮データ:hl wr. hl wr. hl wr. hl wr. hl wr.

この例は「hello world.」と繰り返されるデータを圧縮したものです。「hello world.」は繰り返し表れる文字列ですので、これを「hl wr.」と置き換えています。これにより文字数が少なくなり、データ転送が速くなります。圧縮データを受け取ったブラウザ側で解凍すれば、文字列は元に戻ります。

圧縮データ転送の仕組み

gzip圧縮されたファイルを扱うには、ブラウザがgzipに対応している必要があります。これは、ブラウザ側でgzip圧縮されたファイルを解凍する必要があるためです。しかし、メジャーブラウザは対応しているので、気にする必要はありません。また、Webサーバーもgzipに対応している必要があります。

944-gzip-css-js-gzip圧縮

ブラウザはHTTPヘッダー情報の「Accept-Encoding: gzip」で、gzipに対応していることをWebサーバーに伝えています。その情報を受け取ったWebサーバーはgzip圧縮ファイルを転送したことを示す「Content-Encoding: gzip」を応答データとして返して、合わせてgzip圧縮ファイルを転送します。

最後に、「Content-Encoding: gzip」を受け取ったブラウザはgzip圧縮ファイルを解凍してWebページを表示させます。

gzipファイルを用意する方法

gzip圧縮ファイルは、通常のHTML, CSS, JSファイルがあればWebサーバーで自動生成させることができます。

これは、style.cssのような無圧縮のファイルをWebサーバーに置いておき、ブラウザからgzip圧縮ファイルのリクエストが来たらサーバーがgzip圧縮して転送する方法です。Webサーバーが「mod_deflate」モジュールに対応していれば、サーバーの設定を行うだけで自動で圧縮をしてくれます。これらの主要なレンタルサーバーでは対応しています。

  • さくらインターネット
  • エックスサーバー
  • お名前.com
  • ロリポップ

次のコードは、画像ファイル(gif、jpg、jpeg、png、ico)以外のすべてをgzip圧縮する設定となっています。

<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico)$ no-gzip dont-vary
Header append Vary User-Agent env=!dont-vary
</IfModule>

このコードを「.htaccess」というWebサーバーの設定ファイルに追記します。ファイルの最後尾に追加するのが良いでしょう。.htaccessファイルはFTPソフトでWordPressが置かれているフォルダを確認すると見つかります。

ちなみに、さくらのレンタルサーバー(スタンダードプラン)では、初期状態でこのような記述があり、gzip圧縮されているようです。

<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript
</IfModule>

きちんと設定出来ていれば、Google Chromeでデベロッパーツール(F12)を開いて Network → CSSと進むとページ読み込み時のレスポンスを確認できます。ここでcontent-encodingをみるとgzipとなっていれば設定に問題はありません。

944-gzip-css-js-gzip確認

稀に正常に検知されないこともありますが、HTTP Compression TestというツールでもGzip圧縮されているか確認できます。

gzipはかなり効果がある方法ですが、サーバーの設定が必要なため難しく感じますね。しかし、WordPressを使っている方は安心してください。プラグインを使えば簡単に設定できます。

次の「サーバーの応答時間が遅い(TTFB)」も一緒に改善できる、次のプラグインをおすすめします。

 

原因を再確認する

「サーバーの応答時間が遅い(TTFB)」の改善

サーバーの応答が遅いのは、単にサーバーの性能が低い場合も考えられます。しかし、多くの場合はWordPressのように動的にHTMLコードを生成することが原因です。

これを改善する方法は、次の2つです。

  • サーバーでWordPressページのキャッシュを作成する
  • サーバーのPHPバージョンを7系に設定する

サーバーでWordPressページのキャッシュを作成する

ブラウザでキャッシュデータを保存できるように、サーバーにもキャッシュ データを持たせることができます。

WordPressは、ブラウザからのリクエストがあるたびにPHPの処理でHTMLコードを生成していますが、生成したコードを保存しておけば時間を短縮できます。その分だけサーバーの応答が速くなるということです。

サーバーキャッシュを利用するためのWordPressプラグインはいくつかありますが、この系統のプラグインはサーバー、テーマ、他のプラグインなどとの相性によりうまく動作しないことがあるようです。そのため、いくつか試してみて相性が良いものを選択してください。

私は「Cache Enabler – WordPress Cache」を利用しています。このように設定しておけば、記事の投稿やプラグインの更新のタイミングでキャッシュデータを更新しますので、古い情報が配信されることはありません。

71-ttfb-cache-設定

 

サーバーのPHPバージョンを7系に設定する

WordPressはPHPで動作するシステムですので、PHPの動作速度が速ければサーバーの応答が良くなるということになります。

そのため、サーバーで使用しているPHPのバージョンに注意してください。

PHPはセキュリティや処理速度の向上のためにバージョンアップが行われていて、バージョン5系と7系では処理速度が大きく異なります。処理内容にもよるかと思いますが、7系は5系の2倍以上の速度で処理を実行することができます。

バージョン実行時間(秒)メモリ(MB)
5.39.2275654790.596405029
5.47.4921401980.213706970
5.56.7332905770.213211060
5.67.4800575730.213218689
7.02.1936608310.331372070

PHPのパフォーマンス比較(5.3〜7.0)

処理速度が向上すれば、当然サーバーからのレスポンスは速くなりますので「サーバーの応答時間が遅い(TTFB)」は改善されます。サーバーキャッシュのプラグインを入れておけばあまり意味はないように思えますが、キャッシュデータを作成する速度が速くなりますので、PHPの7系を使いたいところです。

古くからサーバー契約している場合には5系のままになっている可能性もありますので、サーバーの設定を確認してみてください。

 

原因を再確認する