HTMLでアセットを読み込むためのプリロードとプリフェッチの使い方
紹介
ページ上のアセットの読み込みは、最適なウェブパフォーマンスとシームレスなユーザーエクスペリエンスを実現するための重要な部分です。通常、実際のアプリは複数のCSS、フォント、JavaScript、および画像ファイルを読み込みます。これらのアセットはデフォルトでレンダーブロッキングであり、読み込みパフォーマンスを損ないます。
このチュートリアルでは、リソースヒントと呼ばれる新しい機能、例えばプリロードやプリフェッチを探ります。これらのリソースヒントを使用することで、レンダーブロッキングを克服することができます。
前提条件
このチュートリアルを完了するには、次のものが必要です:
- Google Chromeがダウンロードされ、インストールされました。このチュートリアルは、Google Chromeのバージョン86.0.4240.80に基づいています。
- HTMLの理解は、「HTMLでウェブサイトを作る方法」シリーズで見つけることができます。
- JavaScriptの基本的な理解。この「JavaScriptでコーディングする方法」シリーズは、あなたがこれを達成するのを助けます。
ステップ1 — レンダーブロッキングの理解
リソースへのリクエストがレンダーブロッキングの場合、そのリクエストが完了するまで window.onload イベントはトリガーされません。現代のシングルページアプリでは、CSSやJavaScriptファイル、画像などのほとんどのアセットが、動作を開始するためにこのイベントに依存しています。つまり、レンダーブロッキングリクエストが完了するまで、UIの一部はレンダリングや画面表示を開始しないということです。
これを実行するには、標準のボイラープレートHTMLを含むHTMLファイルを作成します。これは、選択したコードエディタで行うことができます:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
</body>
</html>
ヘッダーには、<link>タグを使用して、好みのGoogleフォントにアクセスします。このコードスニペットはRobotoを使用します:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href='https://fonts.googleapis.com/css?family=Roboto:400,600|Material+Icons'>
</head>
<body>
</body>
</html>
<style> タグを追加します。CSSを使用して、すべての p タグの font-family を Roboto に設定します:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href='https://fonts.googleapis.com/css?family=Roboto:400,600|Material+Icons'>
<style>
p {
font-family: Roboto;
}
</style>
</head>
<body>
</body>
</html>
メタデータとCSSが整ったら、<body>内に<p>を作成して「Hello」と表示することができます。
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href='https://fonts.googleapis.com/css?family=Roboto:400,600|Material+Icons'>
<style>
html {
font-family: Roboto;
}
</style>
</head>
<body>
<p> Hello </p>
</body>
</html>
レンダーブロッキングの動作を確認するには、<body>内に<script>タグを追加します。window.onloadを使用して、console.logでメッセージ'Loaded'を表示するJavaScript関数を作成します:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href='https://fonts.googleapis.com/css?family=Roboto:400,600|Material+Icons'>
<style>
html {
font-family: Roboto;
}
</style>
</head>
<body>
<p> Hello </p>
<script>
window.onload = function () {
console.log('Loaded');
}
</script>
</body>
</html>
コードができたら、ChromeでHTMLファイルを開きます。次に、デベロッパーツールを開き、ネットワークタブに移動します。接続をSlow 3Gに下げて、ページを再読み込みします。
CSSファイルが読み込まれた直後に、Loadedメッセージがコンソールに記録されます。次の画像に示すように:
この効果は、より大きなウェブサイトを構築して読み込む際に、より問題を引き起こします。あなたのCSSやJavaScriptの資産、さらには他の多くのものが読み込むのに時間がかかる可能性があります。したがって、あなたのCSSスタイルはすぐには表示されないかもしれません。リソースのプリロードはこの効果を取り除き、読み込みの遅延を防ぐことができます。
ステップ2 — リソースのプリロード
デフォルトのレンダーブロッキングを防ぎ、フォントやCSSなどのページリソースがページライフサイクルの早い段階で読み込まれるようにするには、プリロードを実装する必要があります。rel="preload" 属性値はアセットをプリロードするために使用されます。これは、CSS、JS、フォント、画像など、いくつかのファイル形式に適用できます。プリロードしたいファイルの種類に応じて、対応する as 属性も rel="preload" と一緒に含める必要がある場合があります。CSSの場合、as= は "style" に設定する必要があります。JavaScriptの場合、as= は "script" に設定する必要があります。
HTMLファイルに戻り、前の<link>を変更します。relを"preload"に設定します。as属性を"style"に設定します:
<head>
<link
rel="preload"
as="style"
href='https://fonts.googleapis.com/css?family=Roboto:400,600|Material+Icons'>
<style>
html {
font-family: Roboto;
}
</style>
</head>
Google ChromeでHTMLファイルを開いた状態で、デベロッパーツールに戻り、ネットワークをまだSlow 3Gに設定したままページをロードします。次の画像が示すように、LoadedログがCSSリクエストが始まる直前に表示されるのがわかります:
しかし、CSSスタイルがテキストに適用されていないことに気づいたかもしれません。それは、プリロードやプリフェッチを使用するとリソースが取得されるだけで、適用されないからです。代わりに、プリロードとプリフェッチはリソースをメモリに保持します。リソースがいつ読み込まれるかを定義する必要があります。
フォントは読み込まれたらすぐに適用する必要があります。これを実現するために、onload属性を<link>タグに追加します。onloadを"this.rel='stylesheet'"に設定します。
<link
rel="preload"
as="style"
onload="this.rel = 'stylesheet'"
href='https://fonts.googleapis.com/css?family=Roboto:400,600|Material+Icons'>
onloadでrel属性をstylesheetに設定することで、ブラウザにリソースを使用するよう指示されます。すでにメモリにダウンロードされているため、再度ダウンロードすることはありません。
このonloadソリューションはJavaScriptに依存しているため、元の<link>タグを含む<noscript>タグを追加し、relを"stylesheet"に設定してください:
<link
rel="preload"
as="style"
onload="this.rel = 'stylesheet'"
href='https://fonts.googleapis.com/css?family=Roboto:100,900|Material+Icons'>
<noscript>
<link
rel="stylesheet"
href='https://fonts.googleapis.com/css?family=Roboto:400,600|Material+Icons'>
</noscript>
これにより、JavaScriptが無効になっているか、読み込まれない場合にもフォントが表示されることが保証されます。
あなたは今、ウェブページのアセットをプリロードする方法を知っています。リソースをプリフェッチしたい場合もあるでしょう。
ステップ3 — リソースのプリフェッチ
プリフェッチングは、プリロードと同様に機能します。違いは、リソースをプリフェッチする際に、ブラウザがそのリソースを低優先度と見なすことです。つまり、そのリソースやアセットは少し後でロードされることになります。このため、プリフェッチングは通常、最初に必要とされないが、後の時点で使用されるリソースに実装されます。
HTMLページにプリフェッチングを実装するには、relの値を"prefetching"に変更します:
<link
rel="prefetch"
as="style"
onload="this.rel = 'stylesheet'"
href='https://fonts.googleapis.com/css?family=Roboto:100,900|Material+Icons'>
CSSの事前フェッチングとプリロードは、ウェブパフォーマンスを改善するのに役立ちます。JavaScriptにもプリロードを適用したいかもしれません。JavaScriptのプリロードは、CSSリソースのプリロードとは異なります。
ステップ4 — JavaScriptのプリロード
JavaScriptリソースの事前読み込みは異なる方法で行われます。この例は、事前読み込みに関するGoogle Developersの記事からのもので、次のように示されています:
<link rel="preload" href="used-later.js" as="script">
<!-- ... -->
<script>
var usedLaterScript = document.createElement('script');
usedLaterScript.src = 'used-later.js';
document.body.appendChild(usedLaterScript);
</script>
注意: コードスニペットは、Googleによって作成され、共有された作品から再現されており、Apache 2.0ライセンスの下でライセンスされています。
ここで重要なステップは、ファイルのsrc属性を設定し、それをDOMに挿入することです。
結論
プリロードとプリフェッチを使用すると、リソースの読み込み方法を制御でき、ウェブパフォーマンスを向上させることができます。このチュートリアルでは、CSS、フォント、JavaScriptなどのリソースをプリロードおよびプリフェッチするためのリソースヒントを実装しました。これにより、より高速なプログレッシブウェブアプリを作成する手助けができます。
Angularを使ってプログレッシブウェブアプリを作成するには、この「Angularでプログレッシブウェブアプリを構築する方法」チュートリアルで実現できます。バニラJavaScriptを好む場合は、この「バニラJavaScriptでPWAを構築する方法」チュートリアルがお役に立ちます。


