2015年も暮れようとようとしているのにいまだにCSSを外部ファイルとして読み込んでるの?

釣りっぽいタイトルの記事を書いてみたかったのでやってみました。内容としてはCSSファイルを<link rel=stylesheet...で外部スタイルシートとして読み込むんじゃなくて、style要素にベタ書きしようよという話です。AMP (Accelerated Mobile Pages)の話につながります。

外部CSSファイルはブロッキングCSSリソースになる

『CSSをstyle要素内にベタ書きする』ということに違和感を感じる人もいるかもしれません。普通はlink要素で外部リソースとしてCSSを読み込むからです。ですが、GoogleのPageSpeed Insightsで自分が制作したサイトやページを計測したことのある人なら分かると思いますが、CSSファイルを

<link rel="stylesheet" ...

で読み込むとPageSpeed Insightsで

このページには、ブロッキングCSSリソースが1つあります。これが原因で、ページのレンダリングに遅延が発生しています。

のようなメッセージが出てしまいます(『1つ』の部分は読み込んでいるファイル数によって変わります)。これは

<script src="...

で読み込む外部JavaScriptファイルについても同様です。

JavaScriptファイルを読み込むscript要素の場合は、モダンブラウザに限るとdefer属性を使用することで回避することができます。defer属性をもたせることでブラウザはDOMの解析とレンダリングを続けることができ、JavaScriptはDOM構築後に実行されます。async属性も同様ですが、こちらはスクリプトが読み込まれ次第実行されます。deferの方はDOMContentLoadedイベントの前に、defer属性をもつscript要素の順番に実行されます(例えばjQueryのプラグインの場合はまずjQuery本体を実行する必要があるため、asyncではなくdeferにする必要があります)。詳しくは以前に書いたPageSpeed Insightsについての記事や、HTML5 Experts.jpの『ユーザーの体感速度を高めるためのJavaScriptチューニング(前編)』を参照してください。

CSSの場合にdeferのようなものがあるかというと、残念ながらありません。ではどうすればいいか。回避する一つの方法として、loadCSS.jsを使用して非同期にCSSを読み込む、という対処法がありますが、これだと非同期処理が終わるまでに表示されるHTMLはスタイルが当たらずに崩れます。それを回避したければファーストビューの部分だけをhead要素内に書いておけばいいのですが、そうすると今度はファーストビューより下に読み進めてページの再読み込みをすると、やはりスタイルが当たっていないコンテンツが一瞬表示されます。それも回避しようとなると結局style要素にCSSを全部書く必要があります。

もちろん外部CSSにすることでCSSファイルがキャッシュされて、ページ遷移時にキャッシュからCSSを読み込めるという大きな利点もあります。ですが、なるべくHTTPリクエストを減らして通信回数を抑え、ページの読み込みを速くする方が結果的にユーザエクスペリエンスの向上につながります。

AMPではインラインスタイルのみが認められている

まぁここまでだったらまだ良かったんですが、本題はここからです。それは AMPではインラインスタイルのみが認められている(2015年12月現在) という点です(AMPってなに?という人は海外SEO情報ブログの『モバイルウェブが爆速に! GoogleがAMP (Accelerated Mobile Pages) を立ち上げ』あたりを読んでください)。AMP PROJECTのGet Startedページの”How AMP Speeds Up Performance”には以下のように書かれています:

All CSS must be inline and size-bound

CSS blocks all rendering, it blocks page load, and it tends to get bloated. In AMP HTML pages, only inline styles are allowed. This removes 1 or often more HTTP requests from the critical rendering path compared to most web pages.

Also, the inline style sheet has a maximum size of 50 kilobytes. While this size is big enough for very sophisticated pages, it still requires the page author to practice good CSS hygiene.

意訳すると

CSSはレンダリングやページの読み込みをブロックし、ますます肥大化する傾向にあります。AMP HTMLページではインラインスタイルだけが認められています。こうすることで、多くのウェブページに比べて1つかそれ以上のHTTPリクエストをクリティカルレンダリングパスから減らすことができます。

また、インラインスタイルシートには50KBのサイズ制限があります。これは洗練されたページには十分大きなサイズですが、それでもwebページの制作者は衛生的なCSSを実践する必要があるでしょう。

といったところです。最後は適当ですが、要は汚い、無駄の多いCSSを書くんじゃなくて、整頓された綺麗なCSSを書く練習になるでしょ?ってことなんでしょうか。

GoogleのJohn Mueller曰く、2016年はAMPがSEOのキーワードの一つになるそうです。Googleが検索を支配している以上、モバイルでのAMP対応というのは避けて通れないでしょう。ということは必然的にCSSもインラインスタイルで書くことが多くなっていきそうです。

最後に宣伝:これからはgulp-task-runnerでインラインスタイル化

といってもすべてをインラインスタイルにするのは結構手間です。例えばSCSSなんかでCSSを書いている人は、出来上がったCSSをHTML内にいちいちコピペしないといけません。そんな面倒なことはしたくありません。ということでそれをgulpで全自動してくれるのがgulp-task-runnerです。以前の記事にちょっと書きましたが、gulp-task-runnerではスタイルシートはSCSSで書いて、出来上がったCSSファイルをgulp-file-includeを使ってHTMLファイルのstyle要素にベタっと貼り付けるようにしています。興味のある人は

npm install --save-dev gulp-task-runner

でインストールしてexamplesディレクトリを覗いてみてください。