[79a0317] | 1 | # HTMLMinifier
|
---|
| 2 |
|
---|
| 3 | [![NPM version](https://img.shields.io/npm/v/html-minifier-terser.svg)](https://www.npmjs.com/package/html-minifier-terser)
|
---|
| 4 | [![Build Status](https://github.com/terser/html-minifier-terser/workflows/CI/badge.svg)](https://github.com/terser/html-minifier-terser/actions?workflow=CI)
|
---|
| 5 |
|
---|
| 6 | [HTMLMinifier](https://terser.org/html-minifier-terser/) is a highly **configurable**, **well-tested**, JavaScript-based HTML minifier.
|
---|
| 7 |
|
---|
| 8 | See [corresponding blog post](http://perfectionkills.com/experimenting-with-html-minifier/) for all the gory details of [how it works](http://perfectionkills.com/experimenting-with-html-minifier/#how_it_works), [description of each option](http://perfectionkills.com/experimenting-with-html-minifier/#options), [testing results](http://perfectionkills.com/experimenting-with-html-minifier/#field_testing) and [conclusions](http://perfectionkills.com/experimenting-with-html-minifier/#cost_and_benefits).
|
---|
| 9 |
|
---|
| 10 | [Test suite is available online](https://terser.org/html-minifier-terser/tests/).
|
---|
| 11 |
|
---|
| 12 | Also see corresponding [Ruby wrapper](https://github.com/stereobooster/html_minifier), and for Node.js, [Grunt plugin](https://github.com/gruntjs/grunt-contrib-htmlmin), [Gulp module](https://github.com/jonschlinkert/gulp-htmlmin), [Koa middleware wrapper](https://github.com/koajs/html-minifier) and [Express middleware wrapper](https://github.com/melonmanchan/express-minify-html).
|
---|
| 13 |
|
---|
| 14 | For lint-like capabilities take a look at [HTMLLint](https://github.com/kangax/html-lint).
|
---|
| 15 |
|
---|
| 16 | ## Minification comparison
|
---|
| 17 |
|
---|
| 18 | How does HTMLMinifier compare to other solutions — [HTML Minifier from Will Peavy](http://www.willpeavy.com/minifier/) (1st result in [Google search for "html minifier"](https://www.google.com/#q=html+minifier)) as well as [htmlcompressor.com](http://htmlcompressor.com) and [minimize](https://github.com/Swaagie/minimize)?
|
---|
| 19 |
|
---|
| 20 | | Site | Original size *(KB)* | HTMLMinifier | minimize | Will Peavy | htmlcompressor.com |
|
---|
| 21 | | ---------------------------------------------------------------------------- |:--------------------:| ------------:| --------:| ----------:| ------------------:|
|
---|
| 22 | | [Google](https://www.google.com/) | 45 | **41** | 45 | 46 | 45 |
|
---|
| 23 | | [Stack Overflow](https://stackoverflow.com/) | 115 | **82** | 90 | 92 | 88 |
|
---|
| 24 | | [HTMLMinifier](https://github.com/kangax/html-minifier) | 132 | **105** | 118 | 123 | 118 |
|
---|
| 25 | | [Bootstrap CSS](https://getbootstrap.com/docs/3.3/css/) | 271 | **260** | 269 | 229 | 269 |
|
---|
| 26 | | [Twitter](https://twitter.com/) | 289 | **238** | 282 | 314 | 282 |
|
---|
| 27 | | [BBC](https://www.bbc.co.uk/) | 298 | **233** | 289 | 291 | 269 |
|
---|
| 28 | | [Wikipedia](https://en.wikipedia.org/wiki/President_of_the_United_States) | 574 | **468** | 557 | 578 | 557 |
|
---|
| 29 | | [Amazon](https://www.amazon.co.uk/) | 702 | **343** | 692 | 704 | n/a |
|
---|
| 30 | | [NBC](https://www.nbc.com/) | 844 | **805** | 843 | 844 | n/a |
|
---|
| 31 | | [Eloquent Javascript](https://eloquentjavascript.net/1st_edition/print.html) | 870 | **815** | 840 | 864 | n/a |
|
---|
| 32 | | [New York Times](https://www.nytimes.com/) | 1304 | **1183** | 1301 | 1295 | n/a |
|
---|
| 33 | | [ES draft](https://tc39.github.io/ecma262/) | 6347 | **5686** | 5863 | n/a | n/a |
|
---|
| 34 |
|
---|
| 35 | ## Options Quick Reference
|
---|
| 36 |
|
---|
| 37 | Most of the options are disabled by default.
|
---|
| 38 |
|
---|
| 39 | | Option | Description | Default |
|
---|
| 40 | |--------------------------------|-----------------|---------|
|
---|
| 41 | | `caseSensitive` | Treat attributes in case sensitive manner (useful for custom HTML tags) | `false` |
|
---|
| 42 | | `collapseBooleanAttributes` | [Omit attribute values from boolean attributes](http://perfectionkills.com/experimenting-with-html-minifier/#collapse_boolean_attributes) | `false` |
|
---|
| 43 | | `collapseInlineTagWhitespace` | Don't leave any spaces between `display:inline;` elements when collapsing. Must be used in conjunction with `collapseWhitespace=true` | `false` |
|
---|
| 44 | | `collapseWhitespace` | [Collapse white space that contributes to text nodes in a document tree](http://perfectionkills.com/experimenting-with-html-minifier/#collapse_whitespace) | `false` |
|
---|
| 45 | | `conservativeCollapse` | Always collapse to 1 space (never remove it entirely). Must be used in conjunction with `collapseWhitespace=true` | `false` |
|
---|
| 46 | | `continueOnParseError` | [Handle parse errors](https://html.spec.whatwg.org/multipage/parsing.html#parse-errors) instead of aborting. | `false` |
|
---|
| 47 | | `customAttrAssign` | Arrays of regex'es that allow to support custom attribute assign expressions (e.g. `'<div flex?="{{mode != cover}}"></div>'`) | `[ ]` |
|
---|
| 48 | | `customAttrCollapse` | Regex that specifies custom attribute to strip newlines from (e.g. `/ng-class/`) | |
|
---|
| 49 | | `customAttrSurround` | Arrays of regex'es that allow to support custom attribute surround expressions (e.g. `<input {{#if value}}checked="checked"{{/if}}>`) | `[ ]` |
|
---|
| 50 | | `customEventAttributes` | Arrays of regex'es that allow to support custom event attributes for `minifyJS` (e.g. `ng-click`) | `[ /^on[a-z]{3,}$/ ]` |
|
---|
| 51 | | `decodeEntities` | Use direct Unicode characters whenever possible | `false` |
|
---|
| 52 | | `html5` | Parse input according to HTML5 specifications | `true` |
|
---|
| 53 | | `ignoreCustomComments` | Array of regex'es that allow to ignore certain comments, when matched | `[ /^!/, /^\s*#/ ]` |
|
---|
| 54 | | `ignoreCustomFragments` | Array of regex'es that allow to ignore certain fragments, when matched (e.g. `<?php ... ?>`, `{{ ... }}`, etc.) | `[ /<%[\s\S]*?%>/, /<\?[\s\S]*?\?>/ ]` |
|
---|
| 55 | | `includeAutoGeneratedTags` | Insert tags generated by HTML parser | `true` |
|
---|
| 56 | | `keepClosingSlash` | Keep the trailing slash on singleton elements | `false` |
|
---|
| 57 | | `maxLineLength` | Specify a maximum line length. Compressed output will be split by newlines at valid HTML split-points |
|
---|
| 58 | | `minifyCSS` | Minify CSS in style elements and style attributes (uses [clean-css](https://github.com/jakubpawlowicz/clean-css)) | `false` (could be `true`, `Object`, `Function(text, type)`) |
|
---|
| 59 | | `minifyJS` | Minify JavaScript in script elements and event attributes (uses [Terser](https://github.com/terser/terser)) | `false` (could be `true`, `Object`, `Function(text, inline)`) |
|
---|
| 60 | | `minifyURLs` | Minify URLs in various attributes (uses [relateurl](https://github.com/stevenvachon/relateurl)) | `false` (could be `String`, `Object`, `Function(text)`) |
|
---|
| 61 | | `noNewlinesBeforeTagClose` | Never add a newline before a tag that closes an element | `false` |
|
---|
| 62 | | `preserveLineBreaks` | Always collapse to 1 line break (never remove it entirely) when whitespace between tags include a line break. Must be used in conjunction with `collapseWhitespace=true` | `false` |
|
---|
| 63 | | `preventAttributesEscaping` | Prevents the escaping of the values of attributes | `false` |
|
---|
| 64 | | `processConditionalComments` | Process contents of conditional comments through minifier | `false` |
|
---|
| 65 | | `processScripts` | Array of strings corresponding to types of script elements to process through minifier (e.g. `text/ng-template`, `text/x-handlebars-template`, etc.) | `[ ]` |
|
---|
| 66 | | `quoteCharacter` | Type of quote to use for attribute values (' or ") | |
|
---|
| 67 | | `removeAttributeQuotes` | [Remove quotes around attributes when possible](http://perfectionkills.com/experimenting-with-html-minifier/#remove_attribute_quotes) | `false` |
|
---|
| 68 | | `removeComments` | [Strip HTML comments](http://perfectionkills.com/experimenting-with-html-minifier/#remove_comments) | `false` |
|
---|
| 69 | | `removeEmptyAttributes` | [Remove all attributes with whitespace-only values](http://perfectionkills.com/experimenting-with-html-minifier/#remove_empty_or_blank_attributes) | `false` (could be `true`, `Function(attrName, tag)`) |
|
---|
| 70 | | `removeEmptyElements` | [Remove all elements with empty contents](http://perfectionkills.com/experimenting-with-html-minifier/#remove_empty_elements) | `false` |
|
---|
| 71 | | `removeOptionalTags` | [Remove optional tags](http://perfectionkills.com/experimenting-with-html-minifier/#remove_optional_tags) | `false` |
|
---|
| 72 | | `removeRedundantAttributes` | [Remove attributes when value matches default.](http://perfectionkills.com/experimenting-with-html-minifier/#remove_redundant_attributes) | `false` |
|
---|
| 73 | | `removeScriptTypeAttributes` | Remove `type="text/javascript"` from `script` tags. Other `type` attribute values are left intact | `false` |
|
---|
| 74 | | `removeStyleLinkTypeAttributes`| Remove `type="text/css"` from `style` and `link` tags. Other `type` attribute values are left intact | `false` |
|
---|
| 75 | | `removeTagWhitespace` | Remove space between attributes whenever possible. **Note that this will result in invalid HTML!** | `false` |
|
---|
| 76 | | `sortAttributes` | [Sort attributes by frequency](#sorting-attributes--style-classes) | `false` |
|
---|
| 77 | | `sortClassName` | [Sort style classes by frequency](#sorting-attributes--style-classes) | `false` |
|
---|
| 78 | | `trimCustomFragments` | Trim white space around `ignoreCustomFragments`. | `false` |
|
---|
| 79 | | `useShortDoctype` | [Replaces the `doctype` with the short (HTML5) doctype](http://perfectionkills.com/experimenting-with-html-minifier/#use_short_doctype) | `false` |
|
---|
| 80 |
|
---|
| 81 | ### Sorting attributes / style classes
|
---|
| 82 |
|
---|
| 83 | Minifier options like `sortAttributes` and `sortClassName` won't impact the plain-text size of the output. However, they form long repetitive chains of characters that should improve compression ratio of gzip used in HTTP compression.
|
---|
| 84 |
|
---|
| 85 | ## Special cases
|
---|
| 86 |
|
---|
| 87 | ### Ignoring chunks of markup
|
---|
| 88 |
|
---|
| 89 | If you have chunks of markup you would like preserved, you can wrap them `<!-- htmlmin:ignore -->`.
|
---|
| 90 |
|
---|
| 91 | ### Preserving SVG tags
|
---|
| 92 |
|
---|
| 93 | SVG tags are automatically recognized, and when they are minified, both case-sensitivity and closing-slashes are preserved, regardless of the minification settings used for the rest of the file.
|
---|
| 94 |
|
---|
| 95 | ### Working with invalid markup
|
---|
| 96 |
|
---|
| 97 | HTMLMinifier **can't work with invalid or partial chunks of markup**. This is because it parses markup into a tree structure, then modifies it (removing anything that was specified for removal, ignoring anything that was specified to be ignored, etc.), then it creates a markup out of that tree and returns it.
|
---|
| 98 |
|
---|
| 99 | Input markup (e.g. `<p id="">foo`)
|
---|
| 100 |
|
---|
| 101 | ↓
|
---|
| 102 |
|
---|
| 103 | Internal representation of markup in a form of tree (e.g. `{ tag: "p", attr: "id", children: ["foo"] }`)
|
---|
| 104 |
|
---|
| 105 | ↓
|
---|
| 106 |
|
---|
| 107 | Transformation of internal representation (e.g. removal of `id` attribute)
|
---|
| 108 |
|
---|
| 109 | ↓
|
---|
| 110 |
|
---|
| 111 | Output of resulting markup (e.g. `<p>foo</p>`)
|
---|
| 112 |
|
---|
| 113 | HTMLMinifier can't know that original markup was only half of the tree; it does its best to try to parse it as a full tree and it loses information about tree being malformed or partial in the beginning. As a result, it can't create a partial/malformed tree at the time of the output.
|
---|
| 114 |
|
---|
| 115 | ## Installation Instructions
|
---|
| 116 |
|
---|
| 117 | From NPM for use as a command line app:
|
---|
| 118 |
|
---|
| 119 | ```shell
|
---|
| 120 | npm install html-minifier-terser -g
|
---|
| 121 | ```
|
---|
| 122 |
|
---|
| 123 | From NPM for programmatic use:
|
---|
| 124 |
|
---|
| 125 | ```shell
|
---|
| 126 | npm install html-minifier-terser
|
---|
| 127 | ```
|
---|
| 128 |
|
---|
| 129 | From Git:
|
---|
| 130 |
|
---|
| 131 | ```shell
|
---|
| 132 | git clone git://github.com/terser/html-minifier-terser.git
|
---|
| 133 | cd html-minifier-terser
|
---|
| 134 | npm link .
|
---|
| 135 | ```
|
---|
| 136 |
|
---|
| 137 | ## Usage
|
---|
| 138 |
|
---|
| 139 | Note that almost all options are disabled by default. For command line usage please see `html-minifier-terser --help` for a list of available options. Experiment and find what works best for you and your project.
|
---|
| 140 |
|
---|
| 141 | - **Sample command line:** `html-minifier-terser --collapse-whitespace --remove-comments --remove-optional-tags --remove-redundant-attributes --remove-script-type-attributes --remove-tag-whitespace --use-short-doctype --minify-css true --minify-js true`
|
---|
| 142 |
|
---|
| 143 | ### Node.js
|
---|
| 144 |
|
---|
| 145 | ```js
|
---|
| 146 | const { minify } = require('html-minifier-terser');
|
---|
| 147 |
|
---|
| 148 | const result = await minify('<p title="blah" id="moo">foo</p>', {
|
---|
| 149 | removeAttributeQuotes: true
|
---|
| 150 | });
|
---|
| 151 | result; // '<p title=blah id=moo>foo</p>'
|
---|
| 152 | ```
|
---|
| 153 |
|
---|
| 154 | ## Running benchmarks
|
---|
| 155 |
|
---|
| 156 | Benchmarks for minified HTML:
|
---|
| 157 |
|
---|
| 158 | ```shell
|
---|
| 159 | node benchmark.js
|
---|
| 160 | ```
|
---|
| 161 |
|
---|
| 162 | ## Running local server
|
---|
| 163 |
|
---|
| 164 | ```shell
|
---|
| 165 | npm run serve
|
---|
| 166 | ```
|
---|