-ao- ramune blog

©2020 unio / GO2直営からふるラムネ

Symfony4でHTTP/2 Preload

2019年09月18日
  • Symfony4

HTTP/2 Preload

HTTP/2 Preloadとは、ざっくり言えば

「必要なリソースを先に読み込んでブラウザキャッシュしておく」

ための仕組みです。 CSSや画像、スクリプトなど、実際に適用するタイミングで読み込んでおいたリソースを使うことができるので、 Webアプリのパフォーマンスが良くなる可能性があります。

HTTP/2 Preloadの詳細は様々な解説サイトがあるので、そちらをご覧ください。

SymfonyでPreload

Preloadは、HTMLのlinkタグで rel="preload" を指定するか、 HTTPレスポンスヘッダに Link を指定することで実現できます。

Symfonyでは WebLinkコンポーネント を利用することで、簡単にLinkヘッダを追加できます。

本記事の実行環境&対象バージョン
  • nginx 1.14.0
  • PHP 7.3.10
  • Symfony 4.3.5

まずSymfony WebLinkコンポーネントをインストールします。

                
                    php composer.phar require symfony/web-link
                
            

インストールが完了したらtwigファイルを編集します。 Preloadしたいリソースをpreload関数で書くのがポイントです。

スタイルシートのPreload
                
                    <link rel="stylesheet" href="{{ preload(asset('ramune.css'), {as: 'style', nopush: true}) }}">
                    <link rel="stylesheet" href="{{ preload(asset('code.css'), {as: 'style', nopush: true}) }}">
                
            

オプションの nopush: true はPreloadでリソースを取得することを指し、外すとリソースがサーバからプッシュされるようになります(HTTP/2 Push)。

Preloadはブラウザがリソースを取りに行くのに対し、 Pushはサーバーがリソースを送りつける動きになります。 nginxのブログ にある図(Three configurations were tested to measure the impact of HTTP/2 with server push)がわかりやすいので、 ぜひご覧ください。

jsのプリロードも同様にpreload関数を使います。

jsのPreload
                
                    <script src="preload(asset('build/ramune.js'), {as: 'script', nopush: true})"></script>
                
            

jsファイルのプリロードだけを行いたい場合、素直にlinkタグを書いた方が良いです。 もしHTTP/2 Pushを行いたい場合はHTTPヘッダのLinkが必要なので、 Controllerで制御する方法を検討してください。

scripタグを書かずにPreloadだけしたい場合
                
                    {# 素直にrel="preload"で書く場合 #}
                    {# HTTPレスポンスヘッダのLinkは乗らないので、Pushは不可能 #}
                    <link rel="preload" as="script" href="{{ asset('ramune.js') }}">

                    {# 無理やりpreload関数を使う場合(Linkヘッダに乗る) #}
                    {% set js = preload(asset('build/ramune.js'), {as: 'script', nopush: true}) %}
                
            

WebpackEncoreBundleを利用している場合、webpackのビルド結果ファイルが複数だったりハッシュ値が付いている場合があります。 都度ファイル名を調べてハードコードするのは大変なので、encore_entry_css_filesを使って対象エントリーのファイル名配列を取得します。

WebpackEncoreBundleを利用している場合
                
                    {% for css in encore_entry_css_files('ramune') %}
                        <link rel="stylesheet" href="{{ preload(asset(css), {as: 'style', nopush: true}) }}">
                    {% endfor %}

                    {# jsはencore_entry_js_files関数が用意されている #}
                    {% for js in encore_entry_js_files('ramune') %}
                        ...
                    {% endfor %}
                
            

WebLinkコンポーネントのPreload確認

HTTPレスポンスヘッダにlinkが付与されていればOKです。

Linkヘッダ
HTTP/2 Preload
プロフィール画像
なかのひと:unio

数十年前の牧歌的なインターネッツが好きだった、永遠のモラトリアム人。 ただ、モラトリアムしててもお金は増えないので、しゃかいの厳しさを斜め後ろから眺めつつほそぼそと生活しています。

Twitter GitHub
[広告]