CSS ファイルの最小化を止めた
本ブログでは一時期、転送量を最小限に抑えるために HTML, CSS, JavaScript の不要なコメントやインデント、改行を除去する最小化を行っていました。 HTML に関してはブログを始めた2009年以来、 CSS は Sass を導入した2011〜2012年あたりからだったと思いますが、最小化は転送量削減効果がある一方でデメリットもあります。
言うまでもなく HTML や CSS などの Web で使われるリソースはブラウザの「ソースの表示」機能やパケットキャプチャツール等で中身を確認できます。ユーザースタイルシートを書く、フォーム送信前に送信先(action
属性値)をチェックするなど、ユーザーが直接ソースコードを見る場面は一般的な使い方とまでは言えないものの、それなりには存在するでしょう。
昨今のデスクトップブラウザには開発者ツールが標準搭載されており、 HTML や CSS、またブラウザによっては JavaScript までも整形表示してくれますが、機能が制限されている端末(公共施設の共有端末など)では昔ながらに「ソースの表示」からしかソースを閲覧できないケースもあります。
それでも従量課金制や回線が貧弱な場所からのアクセスも考えると、転送量削減効果の方が優先度が高いと判断し、最小化を行っていたわけですが、数年前からビルド時に Brotli 圧縮ファイルを生成するようにしており、また IE 11 のサポート終了によりすべてのメジャーブラウザが Brotli に対応する状況になったことから、昔と比べれば最小化による転送量削減効果は薄くなってきたと思います。
既に HTML の最小化は止めていますが、このたび CSS の最小化も止めることとし、その際にファイルサイズの比較計測をしたので記録に残しておきます。
本ブログの CSS 構成
本ブログの通常の記事ページでは以下3つの CSS ファイルを <link rel="stylesheet">
ないし <link rel="alternate stylesheet">
で指定しています。
- /style/blog.css
- /style/layout_full.css
- /style/layout_reader.css
これらのうち、ブラウザのスタイルシート切替機構で表示モードを選択するための layout_*.css は Brotli 圧縮後のファイルサイズが 500〜700 バイト程度と小さく無視できるレベルなため、計測は blog.css のみ行いました。
最適化設定ごとのファイルサイズ比較
本ブログでは PostCSS(postcss.org
)を使って CSS ファイルのビルドを行っており、最小化処理自体は CSSNANO(cssnano.co
)をプラグインとして読み込ませて使用しています。
計測は変更前の状態も含めて3パターンを行いました。
default
プリセットベースの最適化(変更前・最小化を行う設定)
まず、変更前の PostCSS 設定(CSSNANO に関する部分のみを抜き出したもの)はこちら。
{
"plugins": {
"cssnano": {
"preset": [
"default",
{
"cssDeclarationSorter": false,
"minifySelectors": false
},
],
}
}
}
CSSNANO のデフォルト設定(cssnano.co
)をベースに、 cssDeclarationSorter(cssnano.co
)と minifySelectors(cssnano.co
)を無効にしています。
-
ちなみに minifySelectors を無効化していた理由は、
::before
,::after
など CSS2 から存在する疑似要素のセレクターが:before
,:after
のようにシングルコロンに変換されてしまうからです。 CSS の疑似要素モジュール仕様の 7. Compatibility Syntaxにおいて、ブラウザはシングルコロンも受け入れるべきであるとされているため、ブラウザは将来的にも旧構文のサポートを続けることが期待できますが、1バイト節約できるからといって古い構文に変換されるのは私の望むところではありません。仕様とブラウザは後方互換性を考慮すべきですが、 Web ページの CSS を閲覧するユーザー(訪問者)は歴史的経緯を学ぶ必要はなく最新の構文だけ理解していれば良い(ので古い構文を提示するのは望ましくない)と考えています。
この設定でファイルサイズは下表で示すようになります。
ファイル名 | ファイルサイズ |
---|---|
blog.css | 35.9 KB (36,844 バイト) |
blog.css.br | 6.42 KB (6,584 バイト) |
最適化しない設定
次に、 CSSNANO による最適化を一切しない設定にしてみました。
{
"plugins": {
}
}
ファイル名 | ファイルサイズ |
---|---|
blog.css | 49.2 KB (50,426 バイト) |
blog.css.br | 8.83 KB (9,045 バイト) |
ファイルサイズは Brotli 圧縮後の比較でも 6.42 KB → 8.83 KB と、 37.4% も増加してしまいました。
lite
プリセットベースの最適化
CSSNANO の適用有無によるファイルサイズ変動の原因のほとんどは CSS コメントの存在によるものです。もし将来的にスタイルガイドを自動作成するための長大なコメントを含めるようになるなど更なる容量増加の可能性もあり、さすがに許容できません。いずれにせよコメントのほとんどは制作上のメモであり、閲覧ユーザーにとって役立つものではないので除去したいところです。
CSSNANO にはいくつかのプリセットが存在しますが、このうち cssnano-preset-lite(www.npmjs.com
)は
- コメントの除去
- 空ルールの除去(
.foo { }
のようにプロパティリストが空なものを消す) - 空白や改行の除去
といった最低限の最適化を行うものであり、自分の欲求に近いものとなっています。このため、 lite プリセットをベースに空白除去のみ無効にすることで「最小化を止めつつファイルサイズの増加は最小限にとどめる」という目的を達成することができそうです。
{
"plugins": {
"cssnano": {
"preset": [
"lite",
{
"normalizeWhitespace": false
}
]
}
}
}
これだけでも良いのですが、 PostCSS の吐き出す CSS は次のように違和感のあるフォーマットとなってしまいます。
.foo{
hoge:value;
fuga:value
}
.foo::before{
piyo:value;
}
個人の好みの範囲内ではありますが、馴染みのあるフォーマットにするため、追加で専用の整形ツールを適用させることにします。制作時に使用している Prettier(prettier.io
)であれば設定も含めてそのまま流用できるため、 PostCSS のビルドによるファイル変更を検知して prettier
コマンドを実行させる記述を package.json
に書き加えます。
{
"scripts": {
"_css:build": "postcss public/style/_src/*.css --base public/style/_src -d public/style",
"_css:format": "onchange -f add -f change -v public/style/*.css -- prettier {file} --write",
"_css:compress": "onchange -f add -f change -v public/style/*.css -- brotlin compress {file} -m 1",
"css": "run-p _css:*",
}
}
これで出力される CSS ファイルはこんな感じになります。
.foo {
hoge: value;
fuga: value;
}
.foo::before {
piyo: value;
}
ファイル名 | ファイルサイズ |
---|---|
blog.css | 40.7 KB (41,726 バイト) |
blog.css.br | 6.57 KB (6,736 バイト) |
Brotli 圧縮後のファイルサイズは最小化していた時と比べて 6.42 KB → 6.57 KB と、 2.3% の増加にとどまっています。この程度なら大きな問題はないでしょう。
ファイルサイズ比較
最終的にファイルサイズの変動をまとめるとこうなりました。
ファイル名 | default ベースの最小化 | lite ベースの最適化 & Prettier 整形 | CSSNANO 非適用 |
---|---|---|---|
blog.css | 35.9 KB (36,844 バイト) | 40.7 KB (41,726 バイト) | 49.2 KB (50,426 バイト) |
blog.css.br | 6.42 KB (6,584 バイト) | 6.57 KB (6,736 バイト) | 8.83 KB (9,045 バイト) |
最小化を止めることにより CSS を直接閲覧した時の見やすさのメリットと、ファイルサイズが増加するデメリットを天秤に掛けると、コメントさえ除去してしまえば転送量の増加はわずかに抑えることができ、 Brotli 圧縮を行う環境下においてはバランスが優れているのではないかと思います。