Webフォントの読み込みは@import
だと色々まずいので、主にlink
要素を使って並列に読み込むわけだけど、これもまた貴重なHTTPリクエスト数を消費するとか、CSSのパース完了が少し遅れるなどあって、完璧な解というわけじゃない。それを非同期にWebフォント定義の含まれるCSSファイルを読み込むようにして、Webフォントのロードをページのレンダリングと並行して行わせるのはどうか、という試み。
非同期化することによりWebフォント定義の含まれるCSSファイルのリクエストとパースが、ページのレンダリングと並行して行われるようになる。head
要素内でlink
要素を直接書いた場合は、Webフォント定義の含まれるCSSのリクエストとパース後にページのレンダリングが始まることが多いので、体感速度(ページのレンダリングの開始までの所要時間)は向上する可能性が高い。
いわゆるソーシャル・ボタンのやっている動的なscript
要素の追加と同じ手法。
(function (d, f) {
var l = d.createElement('link');
l.rel = 'stylesheet';
l.href = f;
var s = d.getElementsByTagName('script')[0];
s.parentNode.insertBefore(l, s);
})(document, 'http://example.com/font/foo.css');
script
要素の代わりにlink
要素を作って突っ込む。置く場所はhead
要素の最後がベストだと思う。複数のWebフォントへの対応は要改善。
とりあえずWebフォントのURLをlink
要素として仕込んでおいて、後でrel="stylesheet"
を追加させることにより非同期化する手法。
<link
href="http://example.com/font/foo.css"
class="async-web-fonts">
<script>
(function () {
var webfonts = document.querySelectorAll('link.async-web-fonts');
for (var i = 0, l = webfonts.length; i < l; i++) {
webfonts[i].rel = 'stylesheet';
}
})();
</script>
rel="stylesheet"
がなければ読みに行かないので、これでも非同期になる。複数のWebフォントのURLを参照するようなケースでも拡張しやすい。見た感じのままDOM操作を最小限に抑えられているけど、総合的なパフォーマンスは動的にlink
要素を突っ込むのとさほど変わらなそう。単体のJavaScriptファイルとして切り出せないのが欠点。
ただし、どちらの非同期読み込み手法でもフォントの読み込み中は他のフォントで表示されるので、FOUTを強制するということになる。フォントのロード完了後にすり替える実装をこのウェブサイトで採用していた時に同じ様にFOUTを強制していて、無視できない程度の数の気になる・戻して欲しいといった意見を貰ったので、この非同期読み込みも採用は慎重に行った方が良さそう。
問題の系統としては、ソーシャルボタンのスクリプトを非同期読込させてページの表示までの速度は上がったけど、遅れて実行されるスクリプトのせいでスクロールがつっかかって悪影響みたいなのとちょっと似てる。こういったページの読み込み速度という面からのみの調整だと漏れてしまう事象について、ユーザーテスト以外のテスト手法があると良いとよく考える。