Last-modifiedとEtagヘッダーを使ってWordPressの動的コンテンツをブラウザキャッシュする方法

以前から、AMPバリデーターの「AMPBench」でAMPページをチェックすると以下のような警告(エラーではない)が出るのが気になっていました。

If-Modified-Since and ETag Headers

[WARNING] Site does not support either “If-Modified-Since” or “ETag” headers: these make amp serving more efficient
[INFO] Header entry for If-Modified-Since not found
[INFO] Header entry for ETag not found

なんだこれ?と思って調べてみると、どうやらIf-Modified-SinceとETagの双方とも、「動的コンテンツをブラウザでキャッシュコントロールするためのHTTPヘッダーのセッティング」みたいです。

今回は既にCDNを利用している方も、利用していない方も今すぐ出来るHTTPヘッダチューニングをご紹介します

この、If-Modified-SinceとETagをWordpressで設定すれば、「訪問者による2回目のアクセスからは負荷軽減ができるかも」というわけで試してみました。

スポンサーリンク
レクタングル(大)広告

WordPressでIf-ModifiedとETagを利用する方法

WordPress用に、更新日を変更した時点でキャッシュが更新される仕様で書いてみました。

以下を、テーマ(子テーマ)のfunctions.phpに貼り付けます。

///////////////////////////////////////
// Last-modified と Etag ヘッダを使って動的コンテンツでもブラウザキャッシュさせる
///////////////////////////////////////
add_action( 'wp','header_last_modified_and_etag', 1 );
if ( !function_exists( 'header_last_modified_and_etag' ) ):
function header_last_modified_and_etag() {
  if (is_singular() /* && is_amp() //AMPページで使う場合はAMP用の条件分岐 */) {
    //Unix Epoc更新日時を取得する
    $modified_time = get_the_modified_time( 'U' );

    // Last-modified と ETag 生成
    $last_modified = gmdate( "D, d M Y H:i:s T", $modified_time );
    //一意となるハッシュ(文字列)
    $etag = '"' . md5( $last_modified . get_permalink() ) . '"';

    // ヘッダ送信
    header( "Last-Modified: {$last_modified}" );
    header( "Etag: {$etag}" );

    // リクエストヘッダの If-Modified-Since と If-None-Match を取得
    $if_modified_since = filter_input( INPUT_SERVER, 'HTTP_IF_MODIFIED_SINCE' );
    $if_none_match = filter_input( INPUT_SERVER, 'HTTP_IF_NONE_MATCH' );

    // Last-modified または Etag と一致していたら 304 Not Modified ヘッダを返して終了
    if ( $if_modified_since === $last_modified || $if_none_match === $etag ) {
      header( 'HTTP', true, 304 );
      exit;
    }
  }
}
endif;

参考 Etag と Last-modified ヘッダを使って動的コンテンツでもブラウザキャッシュさせる – PSI Labs

AMPページのみで処理する場合は、is_amp部分のコメントを外して、AMPページを判別するis_amp関数を作成してください。

設定後の動作を見る

上記のようにカスタマイズして、ブラウザーのデベロッパーツールでヘッダー情報を見てみると、要求ヘッダーには以下のように表示されます。

要求ヘッダー

応答ヘッダーはこんな感じです。

応答ヘッダー

If-Modified-SinceとIf-Modifiedの日時が違っていたらキャッシュが更新されます。

一応、これで2回目の訪問からは、サーバーから「304 (Not Modified)ステータスコード」を返されることによりブラウザのキャッシュが利用されます。

なので、多少なりとも表示の高速化は図れるかもしれません。

Etagは出るブラウザと出ないブラウザがあるみたい。詳しくは調べてません。

Last-modifiedとEtagの難点

これらキャッシュ利用の難点は、「WordPressの更新日が変更されない限りキャッシュが更新されないこと」にあると思います。

WordPressの通常ページ等に今回のカスタマイズを仕込んでおくと、投稿を更新しない限りは、キャッシュが残った状態になります。

なので、例えば以下のような「新着記事ウィジェット」を利用している場合、どんなに投稿をポストしても、新着記事リストが更新されることはありません(キャッシュが残っている限り)。

投稿に関係ない部分は変更されない

その他にも、表示が動的に変更される「関連記事」等も投稿が更新されない限りは、同じブラウザを利用して閲覧した場合、常に同じものが表示されると思います。

なので、本文以外にも動的にコードを生成するページに、今回のカスタマイズは適さないかと思います。そういったページで利用するには、「Wordpressに対して何かしらの変更があった日付」を取得してLast-Modifiedに設定してやる必要はあるかもしれません。

ただ、そうすると頻繁にキャッシュが更新されるので、あまり意味のない設定になる気もします。

まとめ

今回試しに使用してみたLast-modifiedとEtagは、Wordpressで使用するには、そこまで有効ではないような気がします。

使用するとするならば、「ほとんど本文しか表示されないようなAMPページで利用する」とかしかないような。

しかし、AMPページの性質からいって、一見さんが多く、あまり再訪問者が来るようなページではないので、意味のない設定といえば意味のない設定になるかもしれません。

ということで、今回自作のテーマのAMPページとかにLast-modifiedとEtagの利用を検討してみたのですが、採用しないことにしました。

スポンサーリンク
レクタングル(大)広告
レクタングル(大)広告

スポンサーリンク

『Last-modifiedとEtagヘッダーを使ってWordPressの動的コンテンツをブラウザキャッシュする方法』へのコメント

  1. 名前:Chico M 投稿日:2018/09/18(火) 04:37:24 ID:bfa1974b2

    いつも大変、お世話になっております。

    以下の条件分岐の記述について質問があります。

    if (is_singular() /* && is_amp() //AMPページで使う場合はAMP用の条件分岐 */)

    is_amp( )の条件はコメントされていますが、(単独記事の)AMPページのみで設定を行い、通常ページでは設定しない条件設定と解釈しております。

    当初、AMPページのみで設定するようにコードを書いたが、AMPと通常ページで同じ設定のほうが望ましいので、AMPのみの条件をコメント部にして外したと言う理解でよろしいでしょうか?

    また、設定するとETagが検知された旨の表示で、WARNINGは無事に消えるのですが、[INFO] Header entry for If-Modified-Since not foundの方は変わらずに(見つからない)表示されます。

    お忙しいところ、恐れ入りますが、お時間ができた時にご回答頂けると大変助かります。

    よろしくお願い致します。

  2. アバター画像 名前:わいひら 投稿日:2018/09/18(火) 16:07:09 ID:1d339b87b

    当初、AMPページのみで設定するようにコードを書いたが、AMPと通常ページで同じ設定のほうが望ましいので、AMPのみの条件をコメント部にして外したと言う理解でよろしいでしょうか?

    is_amp()部分は、「AMPで表示する場合は、AMPページ判別処理を書いてください」という意味で書きました。
    is_amp()をコメントアウトしたのは、AMPページ以外でも、使用すべきところでは使用すべき処理というのが1つ。
    あとは、is_amp()はSimplicityもしくは、Cocoonでしか書かれていない処理なので、書かれたままで別テーマでテスト動作させようとするとエラーになるからコメントアウトしました。
    ※ややこしいので説明文を追記しておこうと思います。

    インフォメッセージに関しては、実際のページを見てみないと何とも言えないかもしれません。
    ただ、僕もこのコードは実装を諦めて、今は研究も検証もしていないコードなので、必ずしも原因がわかるかはわからないです。

  3. 名前:Chico M 投稿日:2018/09/19(水) 00:37:57 ID:8469317db

    お返事ありがとうございます。

    is_amp()部分は、「AMPで表示する場合は、AMPページ判別処理を書いてください」という意味で書きました。

    仰る意味かと思ったのですが、それ以外の意図・お考えがあるのかもしれないと思ったので、質問しました。お返事、本当にありがとうございます。

    コードを is_amp( ) の条件分岐の部分をコメントで残したまま(そのまま)設置しても、AMPBenchでETagがヘッダーエントリーに見つかったと表示され、PASSになります。If-Modified-Sinceの方は見つからない。(Header entry for If-Modified-Since not found)と表示されます。

    is_amp( )の条件分岐のコメントを外しても、結果は上記と同じになります。

    (そのような結果となったこと、is_singular() && is_amp() だと単独(シングル)のページ(投稿と固定ページ)でかつAMPの時に実行する条件分岐となるので、AMPのみに設定する部分の条件をコメントにしたのかなと思いました。)

    以下のページ(サイト)で本記事の設定コードを実装しています。is_amp( ) の条件分岐の部分はコメントを外してあります。

    https://www.blogging-life.com/cocoon/setup-structured-data-amp-site-logo/?amp=1

    If-Modified-Sinceは、私の環境のブラウザー(ChromeとFirefox)で見ても見つかりませんでした。ETagは表示されます。

    お手数をおかけして誠に恐縮なのですが、よろしくお願い致します。

  4. アバター画像 名前:わいひら 投稿日:2018/09/20(木) 23:42:39 ID:990ae8a3c

    僕の環境で確認した限りでは、表示されていないようです。

  5. アバター画像 名前:わいひら 投稿日:2018/09/20(木) 23:45:04 ID:990ae8a3c

    ヘッダーも表示されているようです。


    僕の環境から表示されているようなので、ちょっと原因はわからないです。

  6. 名前:Chico M 投稿日:2018/09/22(土) 00:26:45 ID:c0cec1bfc

    お忙しいところ、ご確認くださり、本当にありがとうございます。

    ご添付下さったAMP Benchでのテスト結果でも、If-Modified-Sinceの方は見つからない。(Header entry for If-Modified-Since not found)と表示されまていますが、わいひらさんの環境では、ヘッダーにif-modified-sinceが表示されるのですね。私の環境でブラウザーの方では、ヘッダーにif-modified-sinceは表示されませんでした。(見つかりませんでした。)

    原因は分からないとのこと了解致しました。私の方で、何か更新情報などがあった場合は、連絡致します。

    お忙しいところ、ご確認とお返事下さいまして、本当にありがとうございました。

  7. アバター画像 名前:わいひら 投稿日:2018/09/23(日) 07:16:56 ID:7d30fd9a6

    確かに。書いてありました。
    上の方のINFOばかり見ていました^^;
    AMPBench以外で、If-Modified-Sinceをチェックできるツールはないんでしょうかね。
    双方のツールでも、表示が出るかを確認して、原因の切り分けへをやりたいところですね。

    一応、SEOチェキでヘッダーを調べてみた限りでは、「Last-Modified」も出力されているようです。
    http://seocheki.net/http-header.php?url=https://www.blogging-life.com/cocoon/setup-structured-data-amp-site-logo/?amp=1

  8. 名前:Chico M 投稿日:2018/10/01(月) 12:13:13 ID:1bb0e1ebb

    お返事、ありがとうございます。返信が遅くなり、誠に申し訳ございません。

    AMPBench以外で、If-Modified-Sinceをチェックできるツールはないんでしょうかね。
    双方のツールでも、表示が出るかを確認して、原因の切り分けへをやりたいところですね。

    おっしゃる通りですよね。AMPBenchは、他のツールを起動させてテストをしたりしている(例:AMPテスト、構造化データテスティングツール等)ので、If-Modified-Sinceを含む最初の表の結果もどこかのツールを使用している可能性もあると考えています。(または、そこがAMPBenchのオリジナルの部分かもしれません。)

    SEOチェキ!のデータのご添付、ありがとうございます。おっしゃる通りLast-Modifiedは出力されていますね。

    何か分かったことや更新情報を入手した時は、投稿致します。

    お忙しいところ、お時間を割いて頂き、感謝致しております。

  9. 名前:er22 投稿日:2020/05/05(火) 05:41:55 ID:e225c99fe

    ETagに使用する文字はASCII文字であればとくに決まったフォーマット等は定められてはいませんが、ダブルクォーテーションで囲むというルールがあります。

    参考 https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/ETag

    今回の例であれば、
    $etag = md5( $last_modified . get_permalink() );

    $etag = ‘”‘ . md5( $last_modified . get_permalink() ) . ‘”‘;
    とすべき、ということです。

  10. アバター画像 名前:わいひら 投稿日:2020/05/12(火) 12:02:39 ID:72a45ce97

    ご指摘ありがとうございます!
    早速記事の方を修正させていただきました。

  11. 名前:ty 投稿日:2020/06/15(月) 03:53:58 ID:6411ce331

    更新日をベースとして生成したETagでは、例えばカレンダーウィジェットのような日替わりで変わる内容があってもページ自体が更新されなければETagも変わらないので、ページデータ以外の部分で更新された内容があってもキャッシュで隠されて気付けない、という事態も発生します。

  12. アバター画像 名前:わいひら 投稿日:2020/06/15(月) 19:53:28 ID:62a7df663

    それもあると思います。
    とにかく、ページを更新しても他ページに影響のない場合にしか使えないので、あまり有効ではないです。
    なので本文に書いてある通り、僕も採用しませんでした。