41
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

【備忘録】HTMLMinifierの全オプションについて調査した

概要

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&amp;bar=2">&copy;テスト</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の記述(<?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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
41
Help us understand the problem. What are the problem?