はじめに
CSSは画面描画をブロックするリソースとして扱われます。
今回はパフォーマンス改善の一環としてCSSを非同期に読み込ませるテクニックを紹介していきます。
知っている方は結構いるかと思いますので知らない方へ紹介出来たらなと思います!
サイトの表示に時間がかかったりする時に色々なパフォーマンス改善のテクニックがあるかと思います。
例えばJavaScriptを記述する場所はbodyの閉じタグの直前にするとか、async
属性やdefer
属性を付けるとか。
こうすることでJavaScriptに関してはHTMLのレンダリングをブロックせずに実行させることができます。
ではlinkタグで読み込ませるCSSはheadタグ内でしか記述できません。
(JavaScript利用すれば可能みたいですが。)
しかしJavaScriptでCSSをbodyの閉じタグの直前で読み込ませたりするのは手間ですし何より可読性が低くなります。
またlink
タグにはscript
タグのようにasync
やdefer
属性はありません。
さてCSSに関してはどのように改善したらよいでしょうか?
preload
やpreconnect
のResourse Hintsを使う?
いくつかの解決方法がでてきます。
まずはrel
属性を使って、その設定値にpreload
やpreconnect
を記述することです。
※上記記述の値以外にも設定値があるので以下のResourse Hintsを確認してみてください。
https://w3c.github.io/resource-hints/
しかし、preload
に関しては仕様が安定してないので将来的に動きが壊れる可能性があります。
https://w3c.github.io/preload/
また、preconnect
はfirefoxでは未サポートとなっており、SafariなどではTP(Technology Preview)となっているため試験的に入っているようです。
"preconnect" | Can I use... Support tables for HTML5, CSS3, etc
media
属性とonload
属性を使った非同期読み込みテクニック
今回紹介するテクニックは以下のmedia
属性とonload
属性で解決できます。
<link rel="stylesheet" media="print" onload="this.media='all'" ・・・ />
では実際にどのようなことが起きているのでしょうか?
まずmedia="print"
と指定してあげることで、印刷時に適用するCSSであることを宣言します。
この段階では適用するのが印刷時なのでダウンロードのみ行われます。
ロードの実行はレンダリングをブロックしないため非同期で行われます。
そして onload="this.media='all'"
が指定されているためロードが完了するとonload
属性に記述したthis.media="all"
が実行され、linkタグのmedia属性にall
が設定されますall
が設定されることでブラウザにスタイルが適用されるという仕組みになっています。
こうすることで簡単にレンダリング時のパフォーマンスを上げることができます。
最後に
ただし、何でもかんでも非同期化をすればいいというわけではないので使いどころに関しては実装する際にトレードオフを考えて実装してください。
例えばCSSの適用を遅らせることで画面表示のパフォーマンスは上がりますがアクセス時に一瞬スタイリングされていないHTMLのみのページが表示されてしまい少し不格好になってしまいます。
それであればローディング画面を少し表示してあげて画面レンダリングが完了するのを待ってから表示してあげる方がキレイです。
このテクニックは非常に簡単にできますが、本当に自分たちのプロダクトに適した方法なのかを考えてから使用してもらえればなと思います。