概要
HTMLMinifierは細かくカスタマイズ可能なJavaScriptベースのHTML軽量化ツールで、現在まで1,257,900ものリポジトリで使われてきました。
HTML Webpack Pluginのminifyオプションも、Nuxt.jsのbuildプロパティ(html.minify)も、内部的にHTMLMinifierを使っています。
ここではオプションについて備忘として残しておきたいと思います。
インストール
$ npm -D i html-minifier
$ npx html-minifier -V
4.0.0
CLI経由で実行する場合
-o、--output
出力ファイルを指定します。
$ npx html-minifier before.html -o after.html
--input-dir 、--output-dir
入出力するディレクトリを指定すると、入力したディレクトリ内のHTMLファイルについて処理し、出力先ディレクトリに書き出します。複数ファイルでも複数フォルダがあっても、ディレクトリを維持したまま書き出ししてくれます。
$ npx html-minifier --input-dir src --output-dir dist
--file-ext <拡張子>
読み込む拡張子を指定します(例:htm)。
$ npx html-minifier --input-dir src --output-dir dist --file-ext htm
-c、--config-file
JSON形式の設定ファイルを指定できます。
公式のサンプルがあるので参考に。
$ npx html-minifier before.html -o after.html -c setting/config.js
Node.js経由で実行する場合
実際の利用シーンを考え、Node.jsから実行する方法で各種オプションを確認していきます。
下記のようなJSファイルを$ node ***.js
にて叩くものとします。
オプションの並びは公式のリファレンスに沿ったものとなります(アルファベット順)。
const minify = require('html-minifier').minify;
const before = `
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
...
`;
const after = minify(before, {
collapseWhitespace: true
});
console.log(after);
caseSensitive(--case-sensitive)
(--XXX)内はCLI経由時の引数です(以下略)。
caseSensitive: true
属性の大文字と小文字を区別します(デフォルトでfalse)。
属性値は通常minifierにかけるとオプション無しでも小文字に変換されますが、
<a href="#" onClick="test()">aaaa</a>
▼
<a href="#" onclick="test()">aaaa</a>
これを変更しないようします。
<a href="#" onClick="test()">aaaa</a>
collapseBooleanAttributes(--collapse-boolean-attributes)
collapseBooleanAttributes: true
checked="checked"、disabled="disabled"などのブール属性から、属性値を除外します(デフォルトでfalse)。
<input type="checkbox" checked="checked">
▼
<input type="checkbox" checked>
collapseInlineTagWhitespace(--collapse-inline-tag-whitespace)
collapseInlineTagWhitespace: true
インラインタグの周囲の空白を削除します(デフォルトでfalse)。
※ collapseWhitespace: true(--collapse-whitespace)と共に使用
<p>あいうえお <span>かきくけこ</span> </p>
▼
<p>あいうえお<span>かきくけこ</span></p>
collapseWhitespace(--collapse-whitespace)
collapseWhitespace: true
タグ間の空白を削除します(デフォルトでfalse)。
<div> <p> あいうえお </p> </div>
▼
<div><p>あいうえお</p></div>
conservativeCollapse(--conservative-collapse)
conservativeCollapse: true
タグ間の空白を削除するが、半角スペースを空けます(デフォルトでfalse)。
※ collapseWhitespace: true(--collapse-whitespace)と共に使用
<p>あいうえお <span>かきくけこ</span> </p>
▼
<p>あいうえお <span>かきくけこ</span> </p>
continueOnParseError(--continue-on-parse-error)
デフォルトではHTMLのパースエラーが発生したらエラーを表示して処理を中断するが、これを無効にする(デフォルトでfalse)。
<p>あいうえお<
▼
Error: Parse Error: <
となるが、下記を設定することで
continueOnParseError: true
<p>あいうえお<
</p>
customAttrAssign(--custom-attr-assign) [値]
customAttrAssign: [/\?=/]
独自のタグによる条件式をサポートすることを可能にする正規表現の配列(デフォルト値[ ]
)。
<div flex?="{{mode != cover}}"></div>
customAttrCollapse(--custom-attr-collapse) <値>
customAttrCollapse: /ng\-class/
例えば「ng-class」のような独自のカスタム属性を正規表現で指定することで、軽量化できるようにします(デフォルト値なし)。
<p ng-class="
{
one:(flgOne && !flgTwo),
two:flgTwo
}
">あいうえお</p>
▼
<p ng-class="{one:(flgOne && !flgTwo),two:flgTwo}">あいうえお</p>
customAttrSurround(--custom-attr-surround) [値]
独自のタグで囲まれた条件式をサポートする正規表現の配列(デフォルト値[ ]
)。
<input {{#if value}}checked="checked"{{/if}}>
デフォルトでは上記のような独自のタグで囲まれた条件式はパースエラーとなりますが、これを許可させます。正規表現で入り・閉じの配列を指定する必要があります。
customAttrSurround: [[/\{\{#[^}]+\}\}/, /\{\{\/[^}]+\}\}/]]
customEventAttributes(--custom-event-attributes) [値]
customEventAttributes: [/^ng-click$/]
例えば「ng-click」のような独自のイベント属性を正規表現の配列で設定することで、minifyJSで取り扱えるようします(デフォルト値は[ /^on[a-z]{3,}$/ ]
)。
※ minifyJS: true(--minify-js)と共に使用
<button
ng-click="
count = count + 1
">
+1
</button>
▼
<button ng-click="count+=1">
+1
</button>
decodeEntities(--decode-entities)
decodeEntities: true
文字実体参照をデコードします(デフォルトでfalse)。
<a href="/?foo=1&bar=2">©テスト</a>
▼
<a href="/?foo=1&bar=2">©テスト</a>
html5(--no-html5)
HTML5仕様に従って入力を解析します(「html5」がデフォルトでtrue)。
ignoreCustomComments(--ignore-custom-comments) [値]
ignoreCustomComments: [/test_comment/, /ignore_comment/]
残したい特定のコメントを正規表現の配列で指定(デフォルト値[ /^!/ ]
)。
※ removeComments: true(--remove-comments)と共に使用
<!-- test_comment -->残すコメント1<!-- /test_comment -->
<!-- ignore_comment -->残すコメント2<!-- /ignore_comment -->
<!-- other_comment -->消えるコメント<!-- /other_comment -->
▼
<!-- test_comment -->残すコメント1<!-- /test_comment -->
<!-- ignore_comment -->残すコメント2<!-- /ignore_comment -->
消えるコメント
ignoreCustomFragments(--ignore-custom-fragments) [値]
特定のタグ内では処理を無視させたい場合、タグを示す正規表現を配列で指定します(デフォルト値は[ /<%[\s\S]*?%>/, /<\?[\s\S]*?\?>/ ]
)。
※ デフォルトの設定のおかげで、HTMLファイル内のPHPの記述()などは、その中身の処理が無視されます。
例えば、Vue.jsの<template>要素などはタグの体をなしているため、
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
collapseWhitespace: true
とすると下記のように空白が取り除かれますが、
<template v-if="ok"><h1>Title</h1><p>Paragraph 1</p><p>Paragraph 2</p></template>
ignoreCustomFragments: [/<template[\s\S]*?\/template>/]
を足すことで、<template>タグ内を無視してくれます。
includeAutoGeneratedTags(--no-include-auto-generated-tags)
HTMLパーサによって生成されたタグを挿入します(「includeAutoGeneratedTags」がデフォルトでtrue)。
デフォルトでは下記のようにタグに不備がある時、タグを補完してくれますが、
<p><span>aaaa</p>
▼
<p><span>aaaa</span></p>
includeAutoGeneratedTags: false
とすることでこの機能をOFFにします。
<p><span>aaaa</p>
keepClosingSlash(--keep-closing-slash)
空要素の末尾のスラッシュを保持します(デフォルトでfalse)。
デフォルトで空要素の閉じタグは削除されるが、
<hr />
▼
<hr>
keepClosingSlash: true
とすることで、保持されます。
<hr/>
maxLineLength(--max-line-length) <値>
最大行長を指定します(デフォルト値:0)。
maxLineLength: 1
<p>あいうえお</p>
<p>かきくけこ</p>
▼
<p>
あいうえお
</p>
<p>
かきくけこ
</p>
minifyCSS(--minify-css)
minifyCSS: true
「clean-css」を使ってCSSを軽量化します(デフォルトでfalse)。
<style>
*{
margin: 0;
padding: 0;
}
</style>
▼
<style>*{margin:0;padding:0}</style>
minifyJS(--minify-js)
minifyJS: true
「uglify-js」を使ってJavascriptを軽量化します(デフォルトでfalse)。
<script>
console.log('test');
</script>
▼
<script>console.log("test")</script>
minifyURLs(--minify-urls) <値>
minifyURLs: 'https://aaaaaaaaaaaa.com/'
「relateurl」を使ってURLを軽量化します(デフォルトでfalse)。
<a href="https://aaaaaaaaaaaa.com/test/test2/index.html">TEST</a>
<a href="https://aaaaaaaaaaaa.com/test3.html">TEST</a>
▼
<a href="test/test2/">TEST</a>
<a href="test3.html">TEST</a>
preserveLineBreaks(--preserve-line-breaks)
タグ間に改行が含まれる場合、詰めます(デフォルトでfalse)。
※ collapseWhitespace: true(--collapse-whitespace)と共に使用
preserveLineBreaks: true
<p>あいうえお
<span>かきくけこ</span></p>
▼
<p>あいうえお
<span>かきくけこ</span></p>
preventAttributesEscaping(--prevent-attributes-escaping)
属性値のエスケープを防止します(デフォルトでfalse)。
通常、下記のようになるのを、
<a href='#'>link</a>
▼
<a href="#">link</a>
preventAttributesEscaping: true
とすることで
<a href='#'>link</a>
のままにします。
processConditionalComments(--process-conditional-comments)
条件付きコメントの内容を処理する(デフォルトでfalse)。
例えば、collapseWhitespace: true
のみだと条件付きコメント内では軽量化が効きませんが、
<!--[if lt IE 9]>
<p>あいうえお</p>
<p>かきくけこ</p>
<![endif]-->
processConditionalComments: true
とすることで
<!--[if lt IE 9]><p>あいうえお</p><p>かきくけこ</p><![endif]-->
のように条件付きコメント内でも軽量化が効くようになります。
processScripts(--process-scripts) [値]
<script>要素のtypeに対応する文字列を配列で指定します(デフォルト値[]
)。
<script type="application/ld+json">
{
"@context": "http://schema.org/",
"@type": "####"
}
</script>
などはcollapseWhitespace: true
とした場合、<script>内では軽量化が効きませんが、
$ npx html-minifier before.html -o after.html --process-scripts "[\"application/ld+json\"]" --collapse-whitespace
とすることで<script>内でも軽量化が効くようになります。
<script type="application/ld+json">{ "@context": "http://schema.org/", "@type": "####" }</script>
quoteCharacter(--quote-character) <値>
quoteCharacter: "'"
属性値に使用するクォートの種類(「'」または「"」)を指定します。(デフォルト値なし)。
<a href="#">link</a>
▼
<a href='#'>link</a>
removeAttributeQuotes(--remove-attribute-quotes)
removeAttributeQuotes: true
可能であれば、属性を囲むクォートを削除します(デフォルトでfalse)。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
▼
<!DOCTYPE html>
<html lang=ja>
<head>
<meta charset=UTF-8>
removeComments(--remove-comments)
removeComments: true
HTMLコメントを削除します(デフォルトでfalse)。
が消えます。removeEmptyAttributes(--remove-empty-attributes)
removeEmptyAttributes: true
空の属性を削除します(デフォルトでfalse)。
<p id="" style="" title="">foo</p>
<img src="img.png" alt="" height="" id="" class="">
▼
<p>foo</p>
<img src="img.png" alt="" height="">
消える一覧は下記。altなどはちゃんと残してくれます。
class / id / style / title / lang / dir / onfocus / onblur / onchange / onclick / ondblclick / mousedown / mouseup / mouseover / mousemove / mouseout / keypress / keydown / keyup
removeEmptyElements(--remove-empty-elements)
removeEmptyElements: true
空のコンテンツを持つ全ての要素を削除します(デフォルトでfalse)。
<div></div>
<p></p>
▼
removeOptionalTags(--remove-optional-tags)
removeOptionalTags: true
不要なタグを削除します(デフォルトでfalse)。
<html></body></html>など、レンダリングに不要なタグを削除します。
<!DOCTYPE HTML>
<html>
<head>
<title>Hello</title>
</head>
<body>
<p>Welcome to this example.</p>
</body>
</html>
▼
<!DOCTYPE HTML>
<head>
<title>Hello</title>
</head>
<body>
<p>Welcome to this example.</p>
removeRedundantAttributes(--remove-redundant-attributes)
removeRedundantAttributes: true
値がHTML仕様のデフォルトと一致するとき、属性を削除します(デフォルトでfalse)。
<input type="text">
▼
<input>
removeScriptTypeAttributes(--remove-script-type-attributes)
removeScriptTypeAttributes: true
スクリプトタグからtype="text/javascript"を削除します。他のtype属性値は残ります(デフォルトでfalse)。
<script type="text/javascript" src="script.js"></script>
▼
<script src="script.js"></script>
removeStyleLinkTypeAttributes(--remove-style-link-type-attributes)
removeStyleLinkTypeAttributes: true
スタイルタグとリンクタグからtype="text/css"を削除します。他のtype属性値は残ります(デフォルトでfalse)。
<link rel="stylesheet" type="text/css" href="style.css">
▼
<link rel="stylesheet" href="style.css">
removeTagWhitespace(--remove-tag-whitespace)
removeTagWhitespace: true
可能な限り属性間のスペースを削除します(デフォルトでfalse)。
<img src="/img.png" alt="" width="100" height="50">
▼
<img src="/img.png"alt=""width="100"height="50">
sortAttributes(--sort-attributes)
sortAttributes: true
属性をソートします(デフォルトでfalse)。
<img src="/img.png" alt="" width="100" height="50">
▼
<img alt="" src="/img.png" height="50" width="100">
sortClassName(--sort-class-name)
sortClassName: true
class名をアルファベット順でソートします(デフォルトでfalse)。
<p class="red large test2 test1 aiueo">あいうえお</p>
▼
<p class="aiueo large red test1 test2">あいうえお</p>
trimCustomFragments(--trim-custom-fragments)
ignoreCustomFragmentsの周囲の空白を削除します(デフォルトでfalse)。
※ ignoreCustomFragments(--ignore-custom-fragments)と共に使用
collapseWhitespace: true,
ignoreCustomFragments: [/<template[\s\S]*?\/template>/]
とすると下記のようになりますが、
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username">
</template> <template v-else>
<label>Email</label>
<input placeholder="Enter your email address">
</template>
trimCustomFragments: true
を足すことで詰まります。
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address">
</template>
useShortDoctype(--use-short-doctype)
useShortDoctype: true
DOCTYPE宣言を小文字にします(デフォルトでfalse)。
<!DOCTYPE html>
▼
<!doctype html>
ソース内を部分的に除外したい場合
<!-- htmlmin:ignore -->
で除外したい箇所を囲みます。
<!-- htmlmin:ignore -->
<p>Hello world!<br>
Hello world!</p>
<!-- htmlmin:ignore -->
<p>Hello world!<br>
Hello world!</p>
としてcollapseWhitespace: true
のみ設定して実行すると下記の通り。
<p>Hello world!<br>
Hello world!</p>
<p>Hello world!<br>Hello world!</p>
参考サイト
kangax/html-minifier: Javascript-based HTML compressor/minifier (with Node.js support)
Experimenting with HTML minifier — Perfection Kills
HTML minifier revisited — Perfection Kills
HTML minifier
API: build プロパティ - Nuxt.js
html-webpack-plugin - npm