概要
Webkit からフォークされたレンダリングエンジン Blink で使用されている HTMLTokenizer をPHPに移植して、 HTML の Minify(圧縮) を行う「html-minifier」を作りました。
※アルファ版にも満たないため、名称の変更、APIの変更、歴史改変のための push -f がありえます。
できること・できないこと
- 条件付きコメントを残す
- textarea や pre 要素内のテキストのHTMLの意味を変えない
- 開始タグ内のホワイトスペースの最適化
- タグ間の文字列のホワイトスペースの最適化
但し、未実装の部分があります。
- DOCTYPE memo SYSTEM の Tokenizer が未実装(PUBLICはOK)。ここを通る処理は未実装のメソッドがあります。
- invalid なHTMLを処理する際のエラー処理に未実装が多い。
- 実体参照(©等)が最低限
- 最適化が甘い(type="checkbox" → type=checkbox や disabled="disabled" → disabled はまだ未実装)
動機
css の最適化なら LESS や Sass があり、JavaScript ならば、Closure Compiler, YUICompressor, UglifyJS 等のライブラリが存在していますが、 それらを活用する HTML には代表的なものをあまり聞きません。
必要な要件は以下の通りです。
MUST
HTMLの意味を変えない- 条件付きコメントは除外されると、挙動が変わってしまうので、条件付きコメント(ダウンレベルから見えない/見える)を除去しない
- textarea や pre タグ内の要素の空白は意味があるので、最適化を行わない
MUST
アプリケーションレベルで最適化の実行が可能better
最適化のレベルが選択できる- ドキュメントタイプによる最適化の違い(<br>, <br/>, <br />)
- 属性の最適化( type="checkbox" → type=checkbox 一定の条件で「"」は省略できます。また、disabled="disabled" → disabled という最適化もあります。 )
- コメントを除去を On/Off 可能(ライブラリによっては、コメントタグに情報を持たせるものが存在するので、問答無用に削除してもらっては困ります。)
今回はブラウザの処理を理解したいのと、PHPでデバック情報も取得したいので、Blink(現時点では、フォーク前のWebkitのWebcoreとほとんど変わりありません)の処理を移植することにしました。
最適化の分類
HTMLに独自タグを埋め込む方式
Twig (Symfony 等で採用されているテンプレート言語です。)では、spaceless
ブロックによって、そのブロック内のタグ間のホワイトスペースを除外できます。
処理方法は正規表現により、「'/>\s+</', '><'」という形式になっており、タグ間のホワイトスペースを一律削除します。
欠点は、テンプレートの導入とコンテンツの移植が必要なことと、属性の最適化・複雑なホワイトスペース・条件付コメントに対応していないことです。
別のマークアップ言語からHTMLへ変換する方式
最高のパフォーマンスを発揮できる形式だと思われますが、有名どころが haml や slim等で Ruby なのが残念。
欠点は、テンプレートの導入とコンテンツの移植が必要なことです。
HTMLの文字列に対して最適化を実行する方式
今回採用した方式、汎用性がある代わり、ブラウザが解釈するレベルの実装でないと、適切な最適化ができません。
PageSpeed Module
最適化のタイミングは、PHP等の処理が行われた後のHTMLに対して処理されます。
ブラウザ → Webサーバー → PHP等 → Webサーバー(ここ) → ブラウザ
実装は、C言語で、Tokenization の簡略化された処理でトークンを作成後、各種フィルタによって圧縮が行われています。 処理の精度も高く、条件付きコメントを残し、インラインの css や JavaScript まで処理してくれます。
欠点は、Webサーバーにインストールを行うので、アプリケーションレベルで最適化を行うとすると、HTTPリクエストが必要になってしまう点です。
minify
PHP で動作するHTML最適化ライブラリです。 方式は正規表現による置換で最適化を行います。 HTMLの構造は正規表現で表現しきれないので、過剰な最適化が発生してしまいます。
欠点は、最適化が甘いこと、過剰な最適化を行う場合がある、更新が止まっていることです。
kangax/html-minifier
JavaScript で動作するHTML最適化ライブラリです。 方式は、正規表現によるトークンの検出後に最適化を実施する方式です。
開発が止まっておらず、ほしい要件も満たしていました。 Node.js からも利用できるので、PHP内で最適化された結果を取得することも可能ですし、そのままPHPへ移植することも可能です。
使い方
composer からインストールできます。
composer.json
{ "require": { "zaininnari/html-minifier": "0.1.*" } }
<?php require 'vendor/autoload.php'; $html = 'HTML文字列'; $out = zz\Html\HTMLMinify::minify($html);
example.com のTOPページの最適化の様子です。左が最適化前、右が最適化後です。