1. wokamoto

    Posted

    wokamoto
Changes in title
+[WordPress][Nginx] Nginx 1.13.9 に実装された http2_push_preload を使って HTTP/2 push してみる
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,132 @@
+先日リリースされた Nginx ver.1.13.9 に [http2_push](http://nginx.org/en/docs/http/ngx_http_v2_module.html#http2_push) と [http2_push_preload](http://nginx.org/en/docs/http/ngx_http_v2_module.html#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 してみようという試み。
+<img width="956" alt="スクリーンショット 2018-02-23 10.48.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/25964/68e41c5e-418e-a723-56a2-959f325d8ca3.png">
+
+AMIMOTO AMI を使ってる方は、以下のコマンドで Nginx をバージョンアップしておいてください。
+
+```bash
+$ sudo /opt/local/provision
+```
+
+## Nginx 側の設定変更
+
+`http2_push` ディレクティブを使う場合は、 `server` セクション、もしくは `location` セクションに プッシュしたいファイルを列挙していけばいいです。
+
+```conf
+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;` を追加しておくだけです。
+
+```conf
+server {
+ :
+ http2_push_preload on;
+ :
+}
+```
+
+## WordPress で Link ヘッダをだす。
+
+次は、お作法に従って WordPress から適切な `Link` ヘッダを出してあげればいいです。
+ちなみに最初のスクリーンショットにあるサイトは以下のような `Link` ヘッダを出してます。
+
+```text
+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://nginx.org/en/docs/http/ngx_http_v2_module.html#http2_push)
+
+HTTP/2 push したいときは、こんな感じで `Link` ヘッダを出せって言ってますね。
+
+```text
+Link: </app/style.css>; rel=preload; as=style; nopush
+Link: </app/script.js>; rel=preload; as=script
+```
+
+複数のファイルをプッシュしたいときは、カンマ区切りでも良いとも言ってますね。
+
+```text
+Link: </app/style.css>; rel=preload; as=style, </app/script.js>; rel=preload; as=script
+```
+
+さて、WordPress では css や js は [wp_enqueue_style()](https://developer.wordpress.org/reference/functions/wp_enqueue_style/),
+ [wp_enqueue_script()](https://developer.wordpress.org/reference/functions/wp_enqueue_script/) で登録するのがお作法です。
+真っ当なテーマやプラグインなら、これで登録してるはずなので、この情報を使って Link ヘッダを出してみましょう。
+以下のようなプラグインを作って有効にすればオッケーかと思われます。
+
+```php:http2_push.php
+<?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 !