2019年1月8日火曜日

ファーストビューのインライン化で爆速サイトを作る

ファーストビューをインライン化し、少ないCSSでひとまず表示するようにすると体感速度が上がります。 最近はツールも出てきてUnCSS, Criticalの2つが有名みたいです。 他にもPurifyCSSPurgecssDropCSSなど、いくつか似たようなツールがあります。 単純な出力サイズだけを見るならCriticalにはminifyオプションがあるので強いのですが、2つほど注意しないといけない事があります。


1. ファーストビュー以降の処理による表示崩れに注意

これらのツールは非常に便利だけどあくまでファーストビューの最適化だという事には注意しないといけません。 ファーストビューで表示されない部分については、後で遅延ロードする必要がある。 Bootstrapを例に挙げると、modal, popoverあたりにインライン化ツールをそのまま適用すると、ファーストビューの判定外のCSSがたくさんあるので、きちんと動かなくなってしまいます。

この問題には、普通ならpreloadやloadCSSなどのライブラリを使って、本来必要なCSSを再読込して回避する事になるのだろうと思います。 ここでまず最初に注意するべきは、CSSの上書きによって表示が崩れないようにしないといけないという事です。 具体的には !important を付けたり、それでも対処できない部分はクラス名を変更するなどして、上書きされないようにする必要がある。

この !important回りが結構面倒で、Criticalはminifyオプションを付けていると!importantの宣言を書き換えてくるので、CSSを遅延ロードしようとすると表示が崩壊するのです。 これはオプションを指定しなければ済む話かも知れませんが、CLIだと設定できないのがちょっと微妙だなと思いました。 私はNode.jsをそんなに使ってないのでこれは困る。


2. 遅延ロードも最適化する事を考えるべき

ファーストビュー以降のCSSは、一般的にはオリジナルのCSSを読み込んで調整するものだと考えています。 しかし最近のCSSフレームワークのサイズは結構大きいので、不要なCSSだらけ。 本当に遅延ロードするべきなのかという問題もあります。 一部分のCSSを動かすためだけにすべてのCSSを遅延ロードするのはあまりセンスが良くない。

この問題はUnCSS, Criticalではignoreオプション、DropCSSでは回避処理を自前実装する事によって回避できます。 ignoreオプションは名前の通り、ファーストビューの判定から外すためのオプションです。 ファーストビューのインライン化時に、後で使うCSSを削除しないようにする事で、全体のCSSロード量を減らす事ができます。 これはセンスの良い機能だと私は思っていて、ignoreオプションがあるかどうかはインライン化ツールにおける大きな機能差だと思っています。



UnCSSのignoreオプションでどのような指定をするとどれくらいCSSの量を減らせるかを、Bootstrap 4.2.1を用いて確認してみた結果が以下です。 Bootstrapに関わるCSSのサイズを左に表示しています。
11771  -- uncss foo.css
12720  -- uncss foo.css --ignore /\.modal/
16631  -- uncss foo.css --ignore "/\.(modal|popover)/"
140936 (bootstrap.min.css)
BootstrapのCSSをそのまま読み込む場合と比較して1/10くらいのサイズのロードで済んでいる事がわかります。 UnCSSを使えば、使う機能のCSSだけロードできるので、かなり最適化がしやすくなりました。 なおCriticalは色々調整してみたけど表示が崩れてしまってうまくいきませんでした。 良い感じの実行オプションがあれば教えて欲しいです。

あと実際の運用では、Bootstrapの色々な機能を使ってると上記の指定だけではおそらく足りないと思います。 例えばnavbarはまず必要となるでしょう。 こういうのが積み重なっていくとそれなりのサイズになる事が多いと思われる。 なのでファーストビューではUnCSSのオプションなしのものを使って、後から必要な部分だけカスタム化したものをloadCSSなどで読み込むと、通信量とパース量が結構下がるんじゃないかと思います。 この時に同一プロパティを削除したりするとさらに下げられる。

ただそのような同一プロパティの削除によるコスト削減は、これまで理屈上ではわかっていても、それを簡単にできるツールがありませんでした。 しかしDropCSSを少し改良すると、実現できるようになります。 興味のある方は参照してみてください。

カスタムビルドがないようなフレームワークでは割と使えるテクニックかも知れない。

0 件のコメント: