Head Cleaner (仮)

WordPress にプラグインをガンガンと突っ込んでいくと <head> 部に、JavaScript やら CSS やらが、ドンドン追加されて、カオスなことになってしまいます。
そんな状態の自サイトを「YSlow for Firebug」で診断してみると、とても低いスコアになったりしてガックリ来るわけです。
プラグインを外したりしたくなかったりするので、チマチマと修正したりして使っていたんですが、プラグインのバージョンアップのたびに修正するのも面倒です。

そんな折、「WordPress Head Cleaner」というプラグインを見かけました。
これは、ひょっとして <head> 部を自動でキレイにしてくれるのか?と期待してダウンロードしてみたんですが、ソースを見てガッカリ。
ついカッとなって、こんなプラグインを作ってしまいました。

ダウンロード

Head Cleaner@WordPress Plugins
または
Head Cleaner (最適化&高速化)@JSeries

[2/24 6:00 追記] コメント蘭での、ゆりこさんからの指摘により、 Safari では拡張子が .gz の css, JavaScript を認識できないことが判明。
多分 「.gz」の Content-Type が 「text/javascript」 or 「text/css」 になっていないからだと思われます。
Ver.0.3.2 以降で、Safari に対しては gzip 圧縮されたファイルを転送しないように修正しました。
なお IE, Firefox, Opera, Chrome では、問題無いようです。

[2/25 8:00 追記]Ver. 0.4.0 から CSS もすべて結合することができるようになりました。
# ただし、デフォルトでは OFF になっています。
CSS 内の画像ファイル等への相対パスはすべて絶対パスに置き換えます。
制限事項としては、media 属性を気にせずにすべて結合し、media="screen" にしてしまうため、想定外の表示になる可能性もあります。
この辺は、後々修正します。

[2/26 12:30 追記]Ver. 0.5.x から、CSS と JavaScript をそれぞれ CSSTidyjsmin-php で圧縮できるオプションを付けました。
また、コメント欄でのゆりこさんからの指摘により、ユーザエージェントに「AppleWebKit」を含むブラウザ(ただし chrome は除く)からのリクエストがあった場合は .gz ファイルを転送しないように修正しました。
あと、簡単な注意書きを書いた「readme_ja.txt」を同梱したので、読んでやってください。

[3/4 18:30 追記]正式版のリリース準備版を公開しました。
今まで、php ファイルを直接修正していた各種設定は、管理画面の「設定」>「Head Cleaner」から行えます。
また、競合が報告されているプラグインと、その対処法について「readme_ja.txt」に書いてあります。
そちらも、ご一読ください。

[3/5 23:00 追記]正式版リリースしました。

概要

<head> の中身を整形しなおします。

  • IE6 以外の時は先頭に xml 宣言を付与。
  • 重複タグや、不要なタグ、コメント、空白を削除。
  • <meta name="description" /> タグが複数ある場合、一つにまとめる
  • <meta name="keyword" /> タグが複数ある場合、一つにまとめる
  • 話題の <link rel="canonical" /> タグを追加。
  • IE コンディショナルタグを判定して、ブラウザが IE の時だけ対象タグを表示。
  • CSS, JavaScript は、ブラウザが対応していれば gzip 圧縮転送。
  • 複数ある CSS を media 属性ごとに結合して一ファイルにまとめる。
    もちろん、そのファイルには インライン CSS も含まれる。
  • CSSTidy を使用して CSS を最適化する。
  • CSSTidy の最適化オプションを管理画面で指定できる。
  • 複数ある JavaScript をすべて結合して一ファイルにまとめる。
    もちろん、そのファイルには インライン JavaScript も含まれる。
  • JSMin で、JavaScript のソースコードを圧縮する。
  • JavaScript をフッタ領域に移動することもできる。
  • フッタ領域の JavaScript も同様に結合して一ファイルにまとめる。
  • Prototype.js, jQuery, mootools が複数読み込まれている場合、1回だけ読み込むようにする。
  • Prototype.js, jQuery, mootools の読み込み順を修正して、できるだけコンフリクトが発生しないようにする。

※制限事項
・SimpleXML でパースしていますので PHP 5 以降が必須になります。
 また <head> 部が、XML的に正しくないとパース出来ないので、このプラグインは動作しません。

→ Ver. 0.3.0 で、PHP Simple HTML DOM Parser でパースするようにしたため、わりかしルーズな (X)HTML でも通ると思います。
 PHP Simple HTML DOM Parser の制限上、PHP 5 以降必須です。

適用例

どうなるかは、ビフォー・アフタを見てもらえばわかりやすいかな?

適用前

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head profile="http://gmpg.org/xfn/11">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>独断と偏見の何でもレビュー</title>
<meta name="description" content="暇人による、暇人の為の何でもレビューもしくは日常メモ。since Feb. 27, 2005" />
<link rel="stylesheet" href="https://dogmap.jp/wp-content/themes/dogmap/style.css?ver=20081006" type="text/css" media="screen" />
<link rel="shortcut icon" type="image/x-icon" href="https://dogmap.jp/favicon.ico" />
<link rel="icon" type="image/x-icon" href="https://dogmap.jp/favicon.ico" />
<link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="https://dogmap.jp/feed/" />
<link rel="alternate" type="application/atom+xml" title="Atom" href="https://dogmap.jp/feed/atom/" />
<link rel="alternate" type="application/rss+xml" title="ROR" href="https://dogmap.jp/sitemap.xml" />
<link rel="index" href="https://dogmap.jp/" />

<link rel="start" href="https://dogmap.jp/" title="Home" />
<link rel="appendix" href="https://dogmap.jp/about/" title="About" />
<link rel="pingback" href="https://dogmap.jp/xmlrpc.php" />
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://dogmap.jp/xmlrpc.php?rsd" />
<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="https://dogmap.jp/wp-includes/wlwmanifest.xml" /> 
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js'></script>
<script type='text/javascript' src='http://www.google.com/jsapi?key=ABQIAAAAdkdXbSzAaW3Z-fZ0VLiA-BTNLsTCkgAHG6R1rGrc2jhIZmfrTxQ-ueNTQFYw3AGOgb5OImln4sk1QA'></script>
<script type='text/javascript' src='https://dogmap.jp/wp-content/plugins/wp-autopager/js/wp-autopager-0.5.1.min.js?ver=0.5.1'></script>
<script type='text/javascript' src='https://dogmap.jp/wp-content/plugins/wp-lightpop/js/jquery.lightpop-0.7.5.min.js?ver=0.7.5'></script>
<script type='text/javascript' src='https://dogmap.jp/wp-includes/js/jquery/jquery.cookie.js?ver=1.0'></script>
<meta name="generator" content="WordPress 2.7.1" />

<style type="text/css" media="screen,tv,print,handheld"> /*<!&#91;CDATA&#91; */
div.googlemaps{width:300px;height:150px;clear:both;margin:1em auto;border:1px solid #999;line-height:1.25em;text-align:center;overflow:hidden;}
div.googlemaps img {margin:0;padding:0;border:0 none;max-width:none;max-height:none;}
div.googlemaps .infowindow {text-align:left;font-size:0.88em;}
div.googlemaps p {margin:0;text-indent:0;text-align:left;font-size:0.75em;}
/* &#93;&#93;>*/ </style>
<link rel="alternate" media="handheld" type="text/html" href="https://dogmap.jp/" />
<link href="https://dogmap.jp/wp-content/plugins/syntax-highlighter/css/shCore.css?ver=2.0.287" type="text/css" rel="stylesheet" />
<link href="https://dogmap.jp/wp-content/plugins/syntax-highlighter/css/shThemeDefault.css?ver=2.0.287" type="text/css" rel="stylesheet" />

<meta name="robots" content="index,follow" />

<style type="text/css">/*<!&#91;CDATA&#91; */
#content {width: 97.5%;display: block;}
#r_sidebar {width: 17.5%; display: none;}
/*&#93;&#93;>*/</style>

<script type="text/javascript">/*<!&#91;CDATA&#91; */
var addLoadEvent = function(func){ if(typeof jQuery!='undefined'){jQuery(document).ready(func);} else if(typeof google.setOnLoadCallback!='undefined'){google.setOnLoadCallback(func);} else if(typeof wpOnload!='function'){wpOnload=func;} else {var oldonload=wpOnload; wpOnload=function(){oldonload();func();}}};
/* &#93;&#93;>*/</script>
<script type="text/javascript">/* <!&#91;CDATA&#91; */
var googlemapsAnywhereL10n = { language:"ja",markerTitle:"Googleマップに移動",cssPath:"div.googlemaps",errMsgNoData:"エラー: ストリートビューのデータが見つかりません。",errMsgNoFlash:"エラー: お使いのブラウザは Flash に対応していないようです。",errMsgUnknown:"エラー: 不明なエラーです。"};
var lightpop={options:{ imageLoading:'/wp-content/plugins/wp-lightpop/images/lightpop-ico-loading.gif',imageBtnPrev:'/wp-content/plugins/wp-lightpop/images/lightpop-btn-prev.gif',imageBtnNext:'/wp-content/plugins/wp-lightpop/images/lightpop-btn-next.gif',imageBtnClose:'/wp-content/plugins/wp-lightpop/images/lightpop-btn-close.gif',imageBlank:'/wp-content/plugins/wp-lightpop/images/lightpop-blank.gif',flvplayer:'/wp-content/plugins/wp-lightpop/swf/mediaplayer.swf',contentFrameType:'border',overlayBgColor:'#FFF',contentBorder:'1px solid silver',setLinkToTitle:true,Image:{enabled:true,icon:'https://dogmap.jp/wp-content/plugins/wp-lightpop/images/icon-image.png',size:new Array(640,480)},Video:{enabled:true,icon:'https://dogmap.jp/wp-content/plugins/wp-lightpop/images/icon-video.png'},Contents:{enabled:true,icon:'https://dogmap.jp/wp-content/plugins/wp-lightpop/images/icon-contents.png',iframeEnabled:false},YouTube:{enabled:true,icon:'https://dogmap.jp/wp-content/plugins/wp-lightpop/images/icon-youtube.png',param:{'hl':'ja','autoplay':'1','fmt':'18'}},Metacafe:{enabled:false},LiveLeak:{enabled:false},GoogleVideo:{enabled:false},ifilm:{enabled:false},Dailymotion:{enabled:false},superdeluxe:{enabled:false},nicovideo:{enabled:false}},start:function(){}};
/* &#93;&#93;> */</script>

</head>

適用後

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head profile="http://gmpg.org/xfn/11">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<meta name="description" content="暇人による、暇人の為の何でもレビューもしくは日常メモ。since Feb. 27, 2005" />
<meta name="generator" content="WordPress 2.7.1" />
<meta name="robots" content="index,follow" />
<title>独断と偏見の何でもレビュー</title>
<link rel="shortcut icon" type="image/x-icon" href="https://dogmap.jp/favicon.ico" />
<link rel="icon" type="image/x-icon" href="https://dogmap.jp/favicon.ico" />
<link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="https://dogmap.jp/feed/" />
<link rel="alternate" type="application/atom+xml" title="Atom" href="https://dogmap.jp/feed/atom/" />
<link rel="alternate" type="application/rss+xml" title="ROR" href="https://dogmap.jp/sitemap.xml" />
<link rel="index" href="https://dogmap.jp/" />
<link rel="start" href="https://dogmap.jp/" title="Home" />
<link rel="appendix" href="https://dogmap.jp/about/" title="About" />
<link rel="pingback" href="https://dogmap.jp/xmlrpc.php" />
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://dogmap.jp/xmlrpc.php?rsd" />
<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="https://dogmap.jp/wp-includes/wlwmanifest.xml" />
<link rel="alternate" media="handheld" type="text/html" href="https://dogmap.jp/" />
<link rel="canonical" href="https://dogmap.jp/" />
<link rel="stylesheet" type="text/css" href="https://dogmap.jp/wp-content/cache/head-cleaner/css/e938e5ff38c9d1b871d3ef8006dcbfd4.css" media="screen" />
<script type="text/javascript" src="http://www.google.com/jsapi?key=ABQIAAAAdkdXbSzAaW3Z-fZ0VLiA-BTNLsTCkgAHG6R1rGrc2jhIZmfrTxQ-ueNTQFYw3AGOgb5OImln4sk1QA"></script>
<script type="text/javascript" src="https://dogmap.jp/wp-content/cache/head-cleaner/js/c2046402dd21ec3000596d55d75cc257.js"></script>
</head>

何ということでしょう!あんなに汚らしかった HTML コードが、こんなにもスッキリと!
しかも YSlow の結果も、適用前の F(53)と比べると、適用後は D(60)に改善されてます。

今後の予定

あとは指定タグを取り除く機能とか、xml 的に残念なソースでもそれなりにパースする機能とか、重複 JavaScript の削除機能とか付けたいですね。

あと、プラグインの名前も。
JSeries に既に「光画部」があるので、「営繕マン」とか良いかなと思いました。
「島崎くんはイルカの曲芸」です。(謎)

Head Cleaner (仮)」への83件のフィードバック

  1. pyon-yon

    すみません。訂正があります。プラグイン「event-calendar-3-for-php-53」の挿入するinlineのスクリプトは、body内ではなく、元々head要素内にありました。先程head要素に移動した、と書きましたが間違いでしたので、(4)は取り下げます。

    返信
  2. pyon-yon

    wokamotoさま。はじめまして。とても効果的な機能のプラグインと思います。まずは「整列」機能だけ有効にして試用させて頂いてます。更に使い込みたいjsファイルの結合機能についていくつかお尋ねしたいので、よろしくご教示お願いいたします。
    (1)http://www.google.com/jsapi…..の如く、自サバ外から読込むjsは結合の対象から外されるのでしょうか?上記のビフォー・アフターからはそのように見えました。
    (2)関連して、例えばgoogle mapのライブラリが(1)のように結合の対象から外れた場合のことになりますが、多くの場合、ページ内にmapを表示するためにjsを書いて(自作js)、ライブラリを読込むscriptタグを書いた後に、自作jsを読込むことになると思いますが、プラグイン適用後は自作jsがその他多くのjsと結合されて、ライブラリより先に読込まれることになり(ライブラリの読込と順序が逆転し)、google mapが表示されなくなるようなことはないでしょうか?(WP Minifyというプラグインで似た体験をしました)
    (3)結合ファイルに有効期限を設定するオプションの場合ですが、結合対象になっているjsファイルが更新された場合、結合ファイル名(例では/cache/head-cleaner/js/c2046402dd21ec3000596d55d75cc257.js)も自動的に変更され、サイト訪問者のブラウザは更新されたと判断してくれるのでしょうか?それとも、jsファイルの更新を把握した上で、プラグイン管理画面から何らかのアクションを起こすことにより、結合ファイル名を変更するのでしょうか?

    次に整列機能も関連してお尋ねします。
    (4)たとえば、「event-calendar-3-for-php-53」というプラグインは、通常は、body内にinlineでscriptを挿入してきますが、Head Cleanerの有効で、head要素に移動します。しかし、body内に記載されているinlineのscriptでも移動しないで残っているものもありますが、どのように処理の対象を振り分けているのでしょうか?この辺りをよく把握しておくと、結合機能を有効にする際に役立つかもしれないので教えて下さい。

    以上ですが、よろしくお願いいたします。

    返信
  3. ピンバック: GTmetrixでサイトの表示スピード測定!Wordpressブログを高速化する5つのステップ | miyearnZZ Labo

  4. ピンバック: プチカスタマイズ備忘録 | LOVE!?

  5. tokkonoPaPa

    をかもとさん、お世話になります。

    1.4.1 で ‘canonical’ のリンク先が http://…/blog/slow/blog/slow/index.php?… のように、blog/slow/ がダブってしまいます。現在は 1.4.0.4 に戻して使っています。

    この事象は、テーマを含めて自サイトの設定が悪いのか、1.4.1 のバグでしょうか。

    環境は、LaCoocan, php5.2.9, WordPress2.8.6, テーマはiNoveです。

    お手数かけますが、ご教示お願いいたします m(_”_)m

    返信
      1. をかもと 投稿作成者

        tokkonoPaPa さん、どもです。

        連絡遅くなって申し訳ありません。
        tokkonoPaPa さんのご指摘で ‘canonical’ タグの不具合を修正しました。
        今回は、ご報告ありがとうございました。

        返信
  6. ピンバック: ゆっくりと… » Syntax Highlighter 系プラグインの比較と高速化

  7. tahara

    をかもと様のプラグインの数々大変お世話になっております。

    ういろうの国の人様のコメントでも少し触れられていましたが、
    Google Maps Anywhereプラグインが動かなくなります。
    現象としては
    ・「複数の JavaScript を結合する」オプションでGoogle Mapsは出力されるがJSが動かなくなる
    ・「有効なフィルタ」オプションで「GoogleMapsAnywhere::addHead」を「対象外」に設定すると領域にCSSの出力はされるがJSが出力されない
    です。
    GoogleMapsAnywhereクラスのaddHeadメソッドでCSSとJSの出力を行っているようですが、
    JS出力の際のwokControllerクラスのwriteScriptメソッドが効いていないように思われます。

    以下の環境で10/19時点での最新版を使用しております。
    WordPress 3.0.1
    Google Maps Anywhere 1.2.6
    Head Cleaner 1.3.13

    ご確認をよろしくお願いします。

    返信
    1. をかもと 投稿作成者

      tahara さん、はじめまして。レス遅くなり申し訳ありません。

      ちょっと、こちらでは確認できない現象です。
      ご利用されているサーバのPHPのバージョンはいくつでしょうか?

      返信
      1. tahara

        お忙しい中、対応ありがとうございます。

        PHPのバージョンは 5.2.0 です。
        ちなみに現時点での最新バージョンでも同じ現象です。
        Google Maps Anywhere 1.2.6.1
        Head Cleaner 1.3.14

        返信
  8. tokkonoPapa

    wokamotoさん、お世話になります。

    以下の環境ですが、IE用のコンディショナルコメントが削除されてしまいます。

    ・WordPress: 2.9
    ・Theme: iNove 1.4.6 (http://wordpress.org/extend/themes/inove)
    ・Head Cleaner: 1.3.12
    ・設定:「メタタグ “canonical” を追加」のみチェック(デフォルト状態)
    ・有効化している他プラグイン:Akismet 2.3.0、WP Multibyte Patch 1.1.5

    チェックして頂けないでしょうか?

    ウェブサイトの下 wp-content/uploads/2010/08/ にHead Cleaner有効化前後のHTMLファイルを置いてあります。

    ・tokkono.cute.coocan.jp_before.html
    ・tokkono.cute.coocan.jp_after.html

    よろしくお願いします。

    返信
      1. をかもと 投稿作成者

        tokkonoPapa さん、どもです。

        こちらこそ、ご指摘感謝です。
        他にも、なにかお気づきの点があれば、バシバシとご指摘ください。

        返信
  9. ピンバック: 【smm】ソーシャルメディアと連携の取りまくるためのwordpress pluginとかwebサービスとかソーシャルメディア | 古今東西キラーコンテンツ - i-mink.com

  10. ピンバック: WordPressを早くしたいならHead Cleaner

  11. ピンバック: ゆっくりと… » “CSSは上、scriptは下” を簡単に – Head Cleaner 使い方のコツ

  12. ピンバック: WordPressを早くしたいならHead Cleaner « 社会起業家の挑戦日記

  13. ピンバック: WPのパフォーマンスを改善してみようか ?|? gaspanik weblog

  14. ピンバック: Head Cleaner | blog@memo*randum

  15. ピンバック: Moral Hazard!!

  16. ピンバック: Moral Hazard!! » wordpress pluginのコンフリクト

  17. ういろうの国の人

    こんにちは。
    便利に使わせていただいています、が LightBox2プラグインとの相性が悪いようで
    Head Cleaner を有効にすると LightBox2が動作しなくなります。
    全フィルタを対象外にしても、動かないためお手上げです。
    対応してくださると助かります。

    余談ですが、Google Maps Anywhere を使用する際に「複数の JavaScript を結合する」を有効にすると
    うまく動作しませんでした。

    返信
      1. をかもと 投稿作成者

        ういろうの国の人さん、はじめまして。

        Head Cleaner を有効にすると LightBox2が動作しなくなります。
        全フィルタを対象外にしても、動かないためお手上げです。
        対応してくださると助かります。

        現在、WordCamp Kyoto の準備やら何やらで忙しくて検証できていません。
        時間のあるときに確認してみますね。もう少々、お待ちください。

        余談ですが、Google Maps Anywhere を使用する際に「複数の JavaScript を結合する」を有効にすると
        うまく動作しませんでした。

        私は、問題ないんですけどね。
        Google Maps Anywhere・Head Cleaner 共に最新版にアップデートしてもダメでしょうか?
        私の作成しているプラグインは、一部ソースコードを共有しているものがあるので、すべてが最新じゃないとうまく動作しないことが稀にあります。
        この辺は、ご容赦ください。

        返信
  18. こんにちは。
    WPのテーマにwp.Vicuna Ext. Customを使っているのですが、CSSの呼び出しが@import urlとなり、Head CleanerでのCSS最適化等が出来ていないように思います。もし可能でしたら@importにも最適化を対応して頂ければと思います。

    返信
    1. をかもと 投稿作成者

      湊さん、はじめまして。

      現在のバージョンの Head Cleaner では @import url は一段目のみ対応していますが、入れ子になっている場合は対応していません。
      将来、対応するかもしれませんが、とりあえずはテーマを修正することで回避してください m(_ _)m

      返信

コメントを残す

メールアドレスが公開されることはありません。