CSSの非同期読み込み

印刷向けCSSだけじゃなく、ウェブフォントのCSSも非同期で読み込むことにした。FOUTが起こるようになるので、気になったら戻すかも。

var csses = [
  { href: '/styles/print.min.css', media: 'print'; },
  { href: '/fonts/megrim.css'; },
  { href: '/fonts/source-code-pro.css' },
  { href: '/fonts/source-sans-pro.css' }
];
var links = document.createDocumentFragment();
csses.forEach(function (css) {
  var link = document.createElement('link');
  link.rel = 'stylesheet';
  link.href = css.href;

  if (css.media) {
    link.media = css.media;
  }

  links.appendChild(link);
});
document.head.appendChild(links);

オプションでmedia属性を指定できるようにして、印刷向けとウェブフォントのCSSを混ぜられるようにした。一応DocumentFragmentを使ったけど、body要素以下にねじ込むわけじゃないのであんまり意味はなさそう。むしろ遅くなるかも。


CSSに直接@font-face定義を書くと扱いが難しかったり、イニシャル・ペイントまでが遅れたりもする。後者はData URIでフォント・ファイルを埋め込んだりしてなければ気にするほどではないと思ってるけど、メンテナンス性も含めて色々問題は考えられる。

かといってhead要素でlink要素を書いて読み込もうとすると、貴重なHTTPリクエスト枠を消費してしまう。このウェブサイトのようにウェブフォントが必要不可欠な要素ではない場合は、非同期で読み込むのは悪くない妥協だと思う。

他に例えばグローバル・フッターにソーシャル・アイコンを並べ、それをアイコン・フォントで表示してる場合なんかも非同期で良いと思う。いきなりグローバル・フッターから読み始める人もいないと思うので、多少遅れて表示されても問題ないはず。クリティカルなんとか的なアレ。CSSならJavaScriptと違って非同期にしてもCPUを専有したりもしないので、スクロールがカクつくとかもない。

やり過ぎるとわけがわからなくなる危険性が高いので、見える部分だけを優先ではなく、遅れても大丈夫そうな部分を後回しにするような感じで分けてくと良さそうかなと考えてる。