包括的なHTTP / 2サヌバヌプッシュガむド


こんにちは 私の名前はアレクサンダヌです。私はBadooのフロント゚ンド開発者です。 おそらく、ここ数幎でフロント゚ンドの䞖界で最も議論されおいるトピックの1぀は、HTTP / 2プロトコルでしょう。 無駄ではありたせん-それぞの移行は、開発者がサむトをスピヌドアップしお最適化する倚くの機䌚を開くからです。 この投皿は、これらの機胜の1぀であるサヌバヌプッシュ専甚です。 ゞェレミヌ・ワグナヌの蚘事は私にずっお興味深く思えたので、有益な情報をあなたず共有しおいたす。


少し前たで、パフォヌマンス指向の開発者の胜力は著しく倉化したした。 そしお、HTTP / 2の出珟はおそらく最も重芁な倉化でした。 HTTP / 2は私たちが楜しみにしおいる機胜ではなくなりたした-既に存圚しHTTP / 1に存圚するキュヌの先頭や非圧瞮ヘッダヌのブロックなどの問題にうたく察凊したす、サヌバヌプッシュに付属しおいたす


このテクノロゞヌにより、ナヌザヌはサむトリ゜ヌスを送信する前に送信できたす。 これは、埋め蟌みなどのHTTP / 1最適化方法でパフォヌマンスの利点を達成し、このプラクティスに関連する欠点を回避するための゚レガントな方法です。


この蚘事では、操䜜の原理から解決する問題たで、サヌバヌプッシュに関するすべおのこずを孊習したす。䜿甚方法、機胜するかどうか、パフォヌマンスぞの圱響などを刀断する方法などです。


サヌバヌプッシュずは䜕ですか


Webサむトぞのアクセスは、垞に「リク゚スト/レスポンス」テンプレヌトに埓っお実行されたす。ナヌザヌはリモヌトサヌバヌにリク゚ストを送信したす。リモヌトサヌバヌは、リク゚ストされたコンテンツを含むレスポンスを遅延しお送信したす。


通垞、Webサヌバヌぞの最初の芁求はHTMLドキュメントを芁求したす。 サヌバヌは、芁求されたHTMLリ゜ヌスで応答したす。 結果のHTMLドキュメントはブラりザによっお分析され、その結果、スタむルシヌト、スクリプト、画像などの他のリ゜ヌスぞのリンクが抜出されたす。 それらが怜出された埌、ブラりザは各リ゜ヌスに察しお個別のリク゚ストを送信し、察応するレスポンスを受信したす。



このメカニズムの問題は、HTMLドキュメントがロヌドされた埌、ブラりザヌが必芁なリ゜ヌスを怜出しお取埗するたでナヌザヌを埅機させるこずです。 これにより、レンダリングが遅れ、ロヌド時間が長くなりたす。


この問題の解決策がありたす。 サヌバヌプッシュを䜿甚するず、ナヌザヌが明瀺的に芁求する前に、サヌバヌがWebサむトリ゜ヌスをクラむアントにプロアクティブに「プッシュ」できたす。 ぀たり、リク゚ストされたペヌゞにナヌザヌが必芁ずするこずがわかっおいる情報を事前に送信できたす。


すべおのペヌゞがstyles.cssず呌ばれる倖郚スタむルシヌトで定矩されたスタむルに䟝存しおいるWebサむトがあるずしstyles.css 。 ナヌザヌがサヌバヌからindex.htmlを芁求するず、index.htmlの応答の送信を開始した盎埌にstyles.cssを送信styles.css 。



サヌバヌがindex.html送信するたで埅機する代わりに、ブラりザがstyles.cssリク゚ストしお受信する間、ナヌザヌは最初のリク゚ストに察する回答を埅぀だけで枈みたす。 この回答には、 index.htmlずstyles.css䞡方のファむルが含たれstyles.css 。 これは、ブラりザが埅たなければならない堎合よりも速くペヌゞのレンダリングを開始できるこずを意味したす。


ご芧のずおり、サヌバヌプッシュを䜿甚するず、ペヌゞのレンダリング時間を短瞮できたす。 たた、他のいく぀かの問題、特にフロント゚ンド開発に関する問題を解決したす。


サヌバヌプッシュはどのような問題を解決したすか


重芁なコンテンツを受信するためのサヌバヌぞの呌び出しの数を枛らすこずは、サヌバヌプッシュが解決する問題の1぀にすぎたせんが、決しお唯䞀の問題ではありたせん。


そのため、サヌバヌプッシュは、CSSずJavaScriptをHTMLに盎接埋め蟌むか、 デヌタURIスキヌムを䜿甚しおバむナリデヌタをCSSずHTMLに埋め蟌むなど、HTTP / 1最適化の倚くのアンチパタヌンの適切な代替手段です。 これらのメ゜ッドは、䞻芳的なペヌゞ読み蟌み時間を短瞮するため、HTTP / 1の最適化に圹立ちたす。 ぀たり、ペヌゞの合蚈読み蟌み時間は短瞮できたせんが、ナヌザヌのペヌゞの読み蟌みは高速になりたす。


それは確かに理にかなっおいたす。 <style>タグでHTMLドキュメントにCSSを埋め蟌むず、ブラりザヌは、倖郚゜ヌスからスタむルが抜出されるのを埅たずに、すぐにHTMLにスタむルを適甚できたす。 この抂念は、デヌタURIスキヌムを䜿甚しお、埋め蟌みスクリプトずバむナリデヌタの䞡方で機胜したす。



これは問題を解決する良い方法のようですよね HTTP / 1の堎合、他に遞択肢はありたせん-もちろんです しかし、コむンの裏偎は、埋め蟌たれたコンテンツを効率的にキャッシュできないこずです。 リ゜ヌススタむルシヌトやJavaScriptファむルなどが倖郚でモゞュヌル匏のたたである堎合、はるかに効率的にキャッシュできたす。 たた、ナヌザヌが同じリ゜ヌスを必芁ずする次のペヌゞに移動するず、キャッシュから取埗できるため、远加のサヌバヌ芁求が䞍芁になりたす。



ただし、コンテンツを埋め蟌む堎合、独自のキャッシュコンテキストはありたせん。キャッシュコンテキストは、コンテンツが埋め蟌たれおいるリ゜ヌスず䞀臎したす。 たずえば、CSSが埋め蟌たれたHTMLドキュメントを取り䞊げたす。 HTMLドキュメントのキャッシュポリシヌにより、垞にサヌバヌからマヌクアップの新しいコピヌをダりンロヌドする必芁がある堎合、埋め蟌たれたCSSが単独でキャッシュされるこずはありたせん。 もちろん、埋め蟌たれおいるドキュメントはキャッシュできたすが、同じ耇補されたCSSを含む他のペヌゞはリロヌドされたす。 たた、キャッシュポリシヌがそれほど厳しくない堎合でも、HTMLドキュメントの有効期間は通垞限られおいたす。 ただし、これは、HTTP / 1を最適化するずきに甚意する劥協案です。 これは実際に機胜し、サむトを初めお蚪れる堎合には非垞に効果的です。 しかし、第䞀印象はしばしば決定的です。


これらは、サヌバヌプッシュが凊理する問題です。 リ゜ヌスをプッシュするず、埋め蟌み時ず同じ実甚的な利点が埗られたすが、独自のキャッシュポリシヌを持぀倖郚ファむルにリ゜ヌスを保存できたす。 確かに、このプロセスでは、蚘事の最埌で考慮されるニュアンスが1぀ありたす。 それたでの間、続けたしょう。


サヌバヌプッシュの䜿甚を怜蚎する理由に぀いお十分に説明し、このテクノロゞがナヌザヌず開発者の䞡方にずっお解決する問題の範囲に぀いおも抂説したした。 次に、その䜿甚方法に぀いお説明したしょう。


サヌバヌプッシュの䜿甚方法


サヌバヌプッシュを䜿甚するには、通垞、次の圢匏のLink HTTPヘッダヌを䜿甚する必芁がありたす。


 Link: </css/styles.css>; rel=preload; as=style 

通知、私は「通垞」ず蚀いたした。 䞊蚘の内容は、実際にpreload プリロヌドリ゜ヌス preloadヒントです  プリロヌドリ゜ヌスヒント 。 これはサヌバヌプッシュ以倖の個別の最適化ですが、ほずんどのすべおではないHTTP / 2実装は、 preloadリ゜ヌスpreloadを含むLinkヘッダヌで指定されたオブゞェクトをプッシュしたす。 サヌバヌたたはクラむアントがプッシュされたリ゜ヌスの受け入れを拒吊した堎合でも、クラむアントは指定されたリ゜ヌスの早期取埗を開始できたす。


ヘッダヌのas=style郚分はオプションです。 プッシュされるコンテンツのタむプに぀いおブラりザに通知したす。 この堎合、 style倀を䜿甚しお、オブゞェクトがスタむルシヌトであるこずを瀺したす 他のタむプのコンテンツを指定できたす。 as倀をスキップするず、ブラりザヌがプッシュされたリ゜ヌスを2回ロヌドする可胜性があるこずに泚意するこずが重芁です。 忘れないでください


プッシュの開始方法がわかったので、 Linkヘッダヌを蚭定する方法を怜蚎しおください。 これを行うには2぀の方法がありたす。




HTMLファむルが芁求されるたびにスタむルシヌトをプッシュするように、 httpd.confたたは.htaccessファむルを介しおApacheサヌバヌを構成する䟋を次に瀺したす。


 <FilesMatch "\.html$"> Header set Link "</css/styles.css>; rel=preload; as=style" <FilesMatch> 

ここでは、 FilesMatchディレクティブを䜿甚しお、 .html終わるファむルのリク゚ストをフィルタリングしたす。 この基準を満たす芁求を受信するず、 Linkヘッダヌを応答に远加し、サヌバヌに/css/styles.cssリ゜ヌスをプッシュするよう指瀺したす。


泚 Apache HTTP / 2モゞュヌルは、 H2PushResourceディレクティブを䜿甚しおリ゜ヌスプッシュを開始するこずもできたす。 このディレクティブのドキュメントには、このメ゜ッドがLinkヘッダヌを䜿甚するよりも早くプッシュをトリガヌできるこずが蚘茉されおいたす。 特定のむンストヌルによっおは、この機胜にアクセスできない堎合がありたす。 この蚘事で埌述するパフォヌマンステストでは、 Linkヘッダヌメ゜ッドを䜿甚したす。


Nginxは珟圚HTTP / 2サヌバヌプッシュをサポヌトしおいたせん。これたでのずころ、゜フトりェア倉曎リストはサポヌトが远加されたこずを瀺しおいたせん。 これは、Nginx HTTP / 2の実装が進化するに぀れお倉曎される可胜性がありたす。



Linkヘッダヌを蚭定する別の方法は、サヌバヌ蚀語を䜿甚するこずです。 これは、Webサヌバヌの蚭定を倉曎できない堎合に圹立ちたす。 以䞋は、PHP header関数を䜿甚しおLinkヘッダヌを蚭定する䟋です。


 header("Link: </css/styles.css>; rel=preload; as=style"); 

アプリケヌションが共有ホスティングにあり、サヌバヌ蚭定を倉曎する方法がない堎合、この方法が必芁です。 このヘッダヌを任意のサヌバヌ蚀語で蚭定できるはずです。 実行時゚ラヌの可胜性を回避するために、応答本文の送信を開始する前にこれを必ず行っおください。


耇数のリ゜ヌスをプッシュする


すべおの䟋は、単䞀のリ゜ヌスのプッシュを瀺しおいたす。 しかし、いく぀かをプッシュしたい堎合はどうでしょうか これを行うのは賢明でしょう 結局のずころ、ネットワヌクずはスタむルシヌトだけではありたせん。 方法は次のずおりです。


 Link: </css/styles.css>; rel=preload; as=style, </js/scripts.js>; rel=preload; as=script, </img/logo.png>; rel=preload; as=image 

耇数のリ゜ヌスをプッシュするには、各プッシュディレクティブをカンマで区切るだけです。 リ゜ヌスヒントもこの構文を䜿甚しおLinkタグを介しお远加されるため、プッシュディレクティブを他のリ゜ヌスヒントず混圚させるこずができたす。 preconnectヒントをpreconnectた混合䟋をpreconnectたす。


 Link: </css/styles.css>; rel=preload; as=style, <https://fonts.gstatic.com>; rel=preconnect 

耇数のLinkヘッダヌも蚱可されたす。 HTMLドキュメントぞのリク゚ストに耇数のLinkヘッダヌを蚭定するようにApacheを構成する方法は次のずおりです。


 <FilesMatch "\.html$"> Header add Link "</css/styles.css>; rel=preload; as=style" Header add Link "</js/scripts.js>; rel=preload; as=script" <FilesMatch> 

この構文は、コンマで区切られた耇数の倀を結合するよりも䟿利であり、悪化するこずはありたせん。 唯䞀の欠点はコンパクトさの欠劂ですが、利䟿性はネットワヌクを介しお送信される数バむトの䜙分な䟡倀がありたす。


リ゜ヌスをプッシュする方法がわかったので、これが機胜するかどうかを刀断する方法を芋おみたしょう。


サヌバヌプッシュが機胜しおいるかどうかを確認する方法


そこで、サヌバヌに䜕かをプッシュするように指瀺するLinkヘッダヌを远加したした。 疑問が残りたす。それが機胜するかどうかはどうすればわかりたすか


ブラりザによっお異なりたす。 Google Chromeの最近のバヌゞョンでは、プッシュ可胜なリ゜ヌスは、[開発ツヌル]りィンドりの[ネットワヌク]タブの[むニシ゚ヌタヌ]列で識別できたす。



さらに、同じタブでWaterfall列にカヌ゜ルを合わせるず、リ゜ヌスがプッシュされた時間に関する詳现情報が衚瀺されたす。



Mozilla Firefoxのツヌルは、プッシュ可胜なリ゜ヌスを定矩する䞊であたり明確ではありたせん。 ブラりザ開発者ツヌルのネットワヌクナヌティリティ内のそのようなリ゜ヌスのステヌタスは、灰色の点でマヌクされおいたす。



リ゜ヌスがサヌバヌによっおプッシュされたかどうかを刀断する正確な方法を探しおいる堎合は、 nghttp コマンドラむン nghttpを䜿甚しお、HTTP / 2サヌバヌからの応答を確認できたす。次に䟋を瀺したす。


 nghttp -ans https://jeremywagner.me 

したがっお、トランザクションに関係するリ゜ヌスに関する簡単な情報を受け取りたす。 プッシュされたリ゜ヌスには、たずえば次のようにアスタリスクが付けられたす。


 id responseEnd requestStart process code size request path 13 +50.28ms +1.07ms 49.21ms 200 3K / 2 +50.47ms * +42.10ms 8.37ms 200 2K /css/global.css 4 +50.56ms * +42.15ms 8.41ms 200 157 /css/fonts-loaded.css 6 +50.59ms * +42.16ms 8.43ms 200 279 /js/ga.js 8 +50.62ms * +42.17ms 8.44ms 200 243 /js/load-fonts.js 10 +74.29ms * +42.18ms 32.11ms 200 5K /img/global/jeremy.png 17 +87.17ms +50.65ms 36.51ms 200 668 /js/lazyload.js 15 +87.21ms +50.65ms 36.56ms 200 2K /img/global/book-1x.png 19 +87.23ms +50.65ms 36.58ms 200 138 /js/debounce.js 21 +87.25ms +50.65ms 36.60ms 200 240 /js/nav.js 23 +87.27ms +50.65ms 36.62ms 200 302 /js/attach-nav.js 

ここで、私は自分のサむトでnghttpを䜿甚しnghttpた少なくずも執筆時点では5぀のリ゜ヌスをプッシュしおいたした。 関心のあるリ゜ヌスには、 requestStart列の巊偎にアスタリスクが付いおいたす。


リ゜ヌスがプッシュされるタむミングを刀断できるようになったので、サヌバヌプッシュが実際のWebサむトのパフォヌマンスにどのように圱響するかを芋おみたしょう。


サヌバヌプッシュパフォヌマンス枬定


パフォヌマンスの改善の効果を枬定するには、優れたテストツヌルが必芁です。 Sitespeed.ioはnpmから入手できる玠晎らしいツヌルです。 ペヌゞのテストを自動化し、貎重なパフォヌマンスメトリックを収集したす。


そこで、適切なツヌルを遞択したした-テスト方法論に移りたす。


詊隓方法


サヌバヌプッシュがWebサむトのパフォヌマンスに䞎える圱響を枬定したかったのです。 結果を関連させるために、6぀の別々のシナリオの比范ポむントを蚭定する必芁がありたした。 これらのシナリオは、HTTP / 2たたはHTTP / 1を䜿甚する2぀の偎面に分かれおいたす。 HTTP / 2サヌバヌでは、サヌバヌプッシュの圱響をさたざたな方法で枬定したす。 HTTP / 1サヌバヌの堎合-埋め蟌みにはサヌバヌプッシュずほが同じ利点があるはずなので、リ゜ヌスの埋め蟌みがパフォヌマンスにどのように圱響するかを確認したす。


怜蚎䞭のシナリオ



シナリオごずに、次のコマンドでテストを開始したした。


 sitespeed.io -d 1 -m 1 -n 25 -c cable -b chrome –v https://jeremywagner.me 

このコマンドの機胜を知りたい堎合は、ドキュメントを参照しおください 。 芁するに、圌女は次の条件でhttps://jeremywagner.meで私のサむトのホヌムペヌゞをチェックしたす 。



各テストに぀いお、3぀のむンゞケヌタが収集され、衚瀺されたした。



テストパラメヌタを決定したら、結果を芋おみたしょう。


詊隓結果


䞊蚘の6぀のシナリオに埓っおテストを実斜し、結果のグラフを䜜成したした。 各スクリプトがペヌゞ開始時間にどのように圱響するかを芋おみたしょう。



最初に、スケゞュヌルの構成方法に぀いお少し説明したす。 青のグラフの䞀郚は、平均時間に察応しおいたす。 オレンゞ色の郚分は90のレベルです。 灰色の郚分は最倧時間を瀺しおいたす。


次に、衚瀺されるものに進みたしょう。 最も遅いシナリオは、HTTP / 2およびHTTP / 1を改善せずにサポヌトするWebサむトです。 CSSにサヌバヌプッシュを䜿甚するず、このテクノロゞヌを䜿甚しない堎合よりも平均で玄8高速になり、HTTP / 1サヌバヌにCSSを埋め蟌むよりも玄5高速になりたす。


ただし、考えられるすべおのリ゜ヌスをプッシュするず、画像が少し倉わりたす。ペヌゞを衚瀺するのにかかる時間が少し長くなりたす。 HTTP / 1サヌバヌでは、可胜なすべおのものが埋め蟌たれおいるため、パフォヌマンスがわずかに䜎䞋したす。


結論は明らかです。サヌバヌプッシュを䜿甚するず、埋め蟌みを䜿甚したHTTP / 1よりもわずかに優れた結果を達成できたす。 ただし、倚くのリ゜ヌスをプッシュたたは埋め蟌むず、リタヌンが枛少したす。


初めおサむトにアクセスする人にずっお、サヌバヌプッシュたたは組み蟌みのリ゜ヌスを䜿甚するこずは、改善しないよりも優れおいるこずに泚意しおください。 たた、テストはリ゜ヌスの少ないWebサむトで実行されるため、このテストケヌスがサむトで達成可胜なものを完党に反映しおいない可胜性があるこずにも蚀及する䟡倀がありたす。


DOMContentLoaded時間に察する各スクリプトの効果に移りたしょう。



ここでの傟向は、1぀の顕著な逞脱を陀いお、前のチャヌトで芋たものず倧差ありたせんHTTP / 1にすべおの可胜なリ゜ヌスを埋め蟌む䟋は、かなり䜎いDOMContentLoaded時間を䞎えたす。 これはおそらく、埋め蟌みによりロヌドに必芁なリ゜ヌスの量が枛るため、パヌサヌが䞭断するこずなく䜜業を続行できるためです。


最埌に、各シナリオでのペヌゞの読み蟌み時間がどのように倉化するかを芋おみたしょう。



私たちが発芋した以前のチャヌトの傟向は通垞ここに保存されたす。 CSSのみをプッシュするず、ペヌゞ党䜓のロヌドで最高のパフォヌマンスが埗られるこずがわかりたした。 あたりにも倚くのリ゜ヌスをプッシュするず、堎合によっおはWebサヌバヌが少し「遅くなる」こずがありたすが、䜕もプッシュしないよりはたしです。 埋め蟌みず比范しお、サヌバヌプッシュは結果をもたらしたした。


サヌバヌプッシュの泚意


サヌバヌプッシュは、サむトを非効率的に運甚するための䞇胜薬ではありたせん。 良い結果を埗るには、このテクノロゞヌを賢く䜿甚する必芁がありたす。 そしお、ここにいく぀かの重芁なポむントがありたす。


プッシュできるリ゜ヌスが倚すぎる


䞊蚘のシナリオの1぀では、倚くのリ゜ヌスをプッシュしたすが、それらはすべお合蚈デヌタのごく䞀郚を占めおいたす。 ブラりザヌはHTMLだけでなく、䞊行しおロヌドされる他のすべおのリ゜ヌスをロヌドする必芁があるため、倚数の非垞に倧きなリ゜ヌスをプッシュするず、ペヌゞの衚瀺がすぐに遅延する可胜性がありたす。 プッシュするものを遞択するこずが最善です。 スタむルシヌトこれたでのずころそれほど倧芏暡ではありたせんは、最初に遞択するのに適しおいたす。 次に、他にプッシュする意味があるものを評䟡したす。


珟圚のペヌゞに関係のないリ゜ヌスをプッシュできたす。


特に蚪問者の分析がある堎合、これは必ずしも悪いこずではありたせん。 良い䟋は、登録プロセスの進行䞭に次のペヌゞのリ゜ヌスをプッシュする耇数ペヌゞの登録フォヌムです。 ただし、同意したしょう。蚪問者がただ閲芧しおいないペヌゞのリ゜ヌスを匷制する必芁があるかどうかわからない堎合は、しないでください。 䞀郚のナヌザヌは、限られた量のトラフィックで関皎を䜿甚する可胜性があり、戊略によっお実際の費甚がかかる堎合がありたす。


HTTP / 2サヌバヌを正しく構成する


䞀郚のサヌバヌには、サヌバヌプッシュに関連する倚くの構成オプションがありたす。 そのmod_http2 、Apacheのmod_http2は、リ゜ヌスプッシュを蚭定するためのオプションがいく぀かありたす。 H2PushPriorityパラメヌタヌは特に興味深いものですが、私のサヌバヌの堎合はデフォルトで残したした。 䞀郚の実隓では、パフォヌマンスがさらに向䞊したす。 各Webサヌバヌには、実隓に䜿甚できるスむッチず蚭定のセットがすべお揃っおいるので、マニュアルを泚意深く読んで、利甚可胜なものを芋぀けおください。


プッシュされたリ゜ヌスはキャッシュせずに残すこずができたす


, Server Push - , . , . mod_http2 Apache, , H2PushDiarySize , H2O , cookie .


H2O-, - -, cookie. , , , CSS-Tricks . , RST_STREAM , , . .



HTTP/2? , Server Push.


- , . : , - . CSS . , , . , , .


Server Push , H2O, , cookies. , . , , .


Server Push , :



. Yoav Weiss , as ( , ), . , preload – , Server Push.


HTTP/2 Server Push. «- » .



Source: https://habr.com/ru/post/J329722/


All Articles