先日リリースされた Nginx ver.1.13.9 に http2_push と http2_push_preload ディレクティブが実装されました。
Changes with nginx 1.13.9 20 Feb 2018
*) Feature: HTTP/2 server push support; the "http2_push" and
"http2_push_preload" directives.*) Bugfix: "header already sent" alerts might appear in logs when using
cache; the bug had appeared in 1.9.13.*) Bugfix: a segmentation fault might occur in a worker process if the
"ssl_verify_client" directive was used and no SSL certificate was
specified in a virtual server.*) Bugfix: in the ngx_http_v2_module.
*) Bugfix: in the ngx_http_dav_module.
そんなわけで、WordPress が読み込んでるスタイルシートやら、JavaScript やらを HTTP/2 Push してみようという試み。
AMIMOTO AMI を使ってる方は、以下のコマンドで Nginx をバージョンアップしておいてください。
$ sudo /opt/local/provision
$ nginx -v
nginx version: nginx/1.13.9
Nginx 側の設定変更
http2_push
ディレクティブを使う場合は、 server
セクション、もしくは location
セクションに プッシュしたいファイルを列挙していけばいいです。
server {
:
http2_push /wp-content/themes/twentyseventeen/style.css?ver=4.9.4;
:
}
でも、WordPress 使ってるとテーマ変更したり、プラグイン追加しただけで push したい css や js が変わってきますよね。
それに合わせて一々 nginx.conf 書き換えるだなんて正気の沙汰じゃないです。
ここは http2_push_preload
ディレクティブを使っていきましょう。
http2_push_preload
ディレクティブが on
になっていると(デフォルトは off です)、アプリケーションが送出する Link
ヘッダを解釈して勝手に HTTP/2 push してくれます。
なので nginx.conf では、以下のように server
セクションに http2_push_preload on;
を追加しておくだけです。
server {
:
http2_push_preload on;
:
}
WordPress で Link ヘッダをだす。
次は、お作法に従って WordPress から適切な Link
ヘッダを出してあげればいいです。
ちなみに最初のスクリーンショットにあるサイトは以下のような Link
ヘッダを出してます。
Link: </wp-content/plugins/amazon-polly/public/css/amazonpolly-public.css?ver=1.0.0>; rel=preload; as=style, </wp-content/themes/twentyseventeen/style.css?ver=4.9.4>; rel=preload; as=style
Link: </wp-content/plugins/amazon-polly/public/js/amazonpolly-public.js?ver=1.0.0>; rel=preload; as=script, </wp-content/themes/twentyseventeen/assets/js/skip-link-focus-fix.js?ver=1.0>; rel=preload; as=script, </wp-content/themes/twentyseventeen/assets/js/global.js?ver=1.0>; rel=preload; as=script, </wp-content/themes/twentyseventeen/assets/js/jquery.scrollTo.js?ver=2.1.2>; rel=preload; as=script
Link
ヘッダの出し方は以下を参考にしてください。
Preload > Server Push (HTTP/2)
HTTP/2 push したいときは、こんな感じで Link
ヘッダを出せって言ってますね。
Link: </app/style.css>; rel=preload; as=style; nopush
Link: </app/script.js>; rel=preload; as=script
複数のファイルをプッシュしたいときは、カンマ区切りでも良いとも言ってますね。
Link: </app/style.css>; rel=preload; as=style, </app/script.js>; rel=preload; as=script
さて、WordPress では css や js は wp_enqueue_style(), wp_enqueue_script() で登録するのがお作法です。
真っ当なテーマやプラグインなら、これで登録してるはずなので、この情報を使って Link ヘッダを出してみましょう。
以下のようなプラグインを作って有効にすればオッケーかと思われます。
<?php
/*
Plugin Name: HTTP/2 Push
Plugin URI:
Description: HTTP/2 Push
Author: wokamoto
Version: 0.0.1
Author URI: http://dogmap.jp/
License:
Released under the GPL license
http://www.gnu.org/copyleft/gpl.html
*/
add_action('template_redirect', function(){
if ( headers_sent() ) {
return;
}
do_action('wp_enqueue_scripts');
foreach( array('style' => wp_styles(), 'script' => wp_scripts()) as $as => $wp_links ) {
$link = '';
foreach ( $wp_links->queue as $handle ) {
if ( $wp_links->registered[$handle] && ! preg_match('/-ie8$/i',$handle) && 'html5' !== $handle ) {
$wp_link = $wp_links->registered[$handle];
$src = preg_replace('#^https?://[^/]+#', '', $wp_link->src);
$ver = $wp_link->ver ? $wp_link->ver : $wp_links->default_version;
$link .= !empty($link) ? ', ' : '';
$link .= " <{$src}?ver={$ver}>; rel=preload; as={$as}";
//header("Link: <{$src}?ver={$ver}>; rel=preload; as={$as}", false);
}
}
if ( !empty($link) ) {
header("Link:{$link}", false);
}
}
}, 0, 1);
このプラグインの解説は割愛。enqueue されてる css や js を拾ってきて、よしなに Link
ヘッダを作ってくれるプラグインです。
なお、このプラグインと Nginx 1.13.9 で HTTP/2 push を有効にしたサイトは以下になります。
https://lets.ninja/
Let's Ninja !