CSS や javascript の縮小&結合の一発処理を独自作成

2015年1月15日

CSS 最適化

今、使っている WordPress テーマ Simplicity
結構な数の CSS をimport してるので、これを 縮小 & 結合することにした。
(ついでに、javascript も)

ちなみに、世間的には「圧縮」とか言うこともあるけど、
圧縮って Gzip にすることやろ?
正確には「最適化」とか「縮小」だと思うw

プラグインとかライブラリは使わない

便利な世の中になったもんで、
Wordpress なら、こういった処理を
勝手にやってくれるプラグインとか、たくさんある

なので、おいらも試してみた。

色々と弊害があるのでプラグインは使わんことにした

WordPress なら有名どころで、
Head Cleaner とか Autoptimize とかあって、
自動的に CSS や javascript を最適化して結合してくれる。

でも、動的だったり、膨大にキャッシュしたり、
どうにも弊害が多い。

おいらは、静的に最適化したいのでござる (・ω・`)

手動ならば、Online JavaScript/CSS Compressor
なんてものもあるんだけど、CSS に手を加えるたびに
いちいち手動でなんかやってられんwww

だったら、独自に作成するしかない

php のライブラリも使わないことにしたw

独自に作成するなら php のライブラリ使えば簡単だよね。
有名どころで、YUI Compressor を利用してみた。

でも、なんか・・・
おいらが期待してる動作をしてくれなかった・・・

2015/01/19 追記:
最新バージョンで思った通りの動作をしてくれたので
YUI Compressor 使うことにしました
記事1記事2

なので、

自分の環境にあったものを、自分のためだけに作る

っていう方針にしたw

作ってみる

とりあえず、処理の流れ

  1. WordPress で使用してるテーマディレクトリ内を走査して
    .css ファイル(.min.css 除く)を再帰的に見つけ出して縮小。
    .min.css の拡張子で保存する。
  2. css ファイル内で import されてるものがあったら
    それを親ファイルに結合。
  3. 外部 CSS を結合。
  4. 再び、テーマディレクトリ内を走査して .js ファイル(.min.js 除く)を縮小。
    .min.js の拡張子で保存する

javascript は、下手に結合すると何が起きるか分からんので、
とりあえず、縮小するだけにとどめた。

CSS の縮小

処理1 の .css ファイルの縮小は、結構簡単。
たぶん、以下の正規表現でいけると思う(たぶん)

$css = preg_replace( array('{\t|\r|\n}', '{(/\*(.*?)\*/)}'), "", $css);
$css = preg_replace( array('{([\(|\[])\s*}', '{\s*([\)|\]])}'), '$1', $css );
$css = preg_replace( "/\s*([\{|\}|:|;|'|\"|,])\s*/", '$1', $css );
$css = preg_replace( "/\s+/", " ", $css );

import されてる CSS を親に結合

処理2 の import されてる .css ファイルの結合も、比較的簡単

@import の url 部分だけ抜き出して
@charset と @import を消す。

preg_match_all( "/@import[^;]*url\s*\((.+?)\)[^;]*;/i", $css, $import_array );
$css = preg_replace( "/@charset[^;]+\;/i", "", $css );
$css = preg_replace( "/@import[^;]*url\s*\(.+?\)[^;]*;/i", "", $css );

あとは、抜き出した($import_array に入れた)パスの CSS を結合するだけ。
この時、CSS の解釈優先順位的に import されてるものが上に記述されるようにしないといかん。

本当は @charset に合わせてエンコードしないといかんのだが、
自分の環境で、別々の charset なんてあり得ないからやめたw

外部 CSS を結合

これは、ちょっと面倒くさい。
CSS が格納されたディレクトリが別々の場合。
background 等のパスの記述が

background: url(img/ahoaho.png);

だったり、

background: url('./ahoaho.png');

だったり、

background: url("../../img/ahoaho.png");

だったり、

パスがバラバラだから。
なので、この url を全て /wp-content で始まるパスに変換
(http://、https:// で始まるものは除く)
ただ、特殊な部分で、base64 に変換した画像などが埋め込まれてる場合があるので、

url(‘data:~’);

とかで始まるものは除外する処理にした。
たぶん、これで大丈夫。

また、注意点として、import された CSS と違って、
CSS の解釈優先順位が後から読み込まれたものが優先されるので、
元ファイルの後ろに結合してやらんといかん。

こーいう部分、面倒くさいわー (´Д`)

Javascript の縮小

これ、結構やっかいな気がする (・ω・`)
とりあえず、自分環境で動けばいいので、
以下の正規表現で、テキトーに縮小した・・・

// コメント削除
$js = preg_replace( "/([\{|\}|;|'|\"|,])\s*?\/\/.+?\n/", "$1\n", $js );
$js = preg_replace( "/\n[\s|\t]*?\/\/.+?\n/", "\n", $js );
$js = preg_replace( array('{\n\/\/.+}','{\A\/\/.+}'), "", $js );
$js = preg_replace( "/\/\*(.*?)\*\//s", "", $js);
// 消しても大丈夫そうな改行とか空白削除
$js = preg_replace( "/\s*([\+|\-|=|\:|;|,])\s*/", '$1', $js );
$js = preg_replace( array('{\n\s+}','{\A\n}'), "", $js );
$js = preg_replace( "/\r*\n*([\{|\}|\(|\)])\r*\n*/", '$1', $js );

2015/01/19 追記:
動作しない Javascript があったので、ちょこっと修正しました

2015/01/21 追記:
動作しない Javascript があったので、ライブラリ使うことにしました(記事2) orz

今のところ、おいらの環境では大丈夫だけど、
他の javascript が全部、これで OK なのか分からん。
もっとキレイで安全なコードがあったら、誰か教えてください・・・

今回やらなかったこと

プラグインで自動的に挿入される CSS や javascript は
静的に保存して良いのか分からんものが多いので、無視することにした。

最適化した結果

ボタン一発で、縮小・結合できるようになったので、
Wordpress テーマの head 内の CSS を style.min.css だけにして、
実際に動かしてみた。

head 内が style.min.css だけになってスッキリ ヽ(´ー`)ノ

PageSpeed Insights

PageSpeed Insights の結果。

PC

最適化前

PC最適化前

最適化後

PC最適化後

モバイル

最適化前

モバイル最適化前

最適化後

モバイル最適化後

PC で 3点アップ。モバイルで7点アップw
まぁ、微々たるものだね。

体感速度

体感速度に関しては、変化なんてあるわけがないw

もともとの CSS ファイルの総サイズが 113.7KB
最適化後の CSS ファイルのサイズは、84.1KB

29.6 KB しか削減できてないw

そもそも、Gzip で圧縮してやれば、最適化せずとも
113.7KB → 24.3KB になる。

Gzip での圧縮なら 89.4KB 削減できるもんw

まぁ、最適化 & 圧縮であれば、
113.7KB → 17.6 KB になるので、約7分の1

悪くはない。

だが、重要なのは、最適化より、やっぱり圧縮だと思うw

WordPress

Posted by るな