Modular HTML minifier, built on top of the PostHTML. Inspired by cssnano.
Website | Source (KB) | html-minifier | htmlnano |
---|---|---|---|
stackoverflow.com | 243 | 193 | 201 |
github.com | 24 | 18 | 21 |
en.wikipedia.org | 64 | 56 | 60 |
npmjs.com | 39 | 29 | 27 |
Avg. minify rate | 0% | 21% | 17% |
npm install --save-dev gulp-htmlnano
var gulp = require('gulp');
var htmlnano = require('gulp-htmlnano');
var options = {
removeComments: false
};
gulp.task('default', function() {
return gulp
.src('./index.html')
.pipe(htmlnano(options))
.pipe(gulp.dest('./build'));
});
var htmlnano = require('htmlnano');
var options = {
removeEmptyAttributes: false, // Disable the module "removeEmptyAttributes"
collapseWhitespace: 'conservative' // Pass options to the module "collapseWhitespace"
};
htmlnano.process(html, options).then(function (result) {
// result.html is minified
});
Just add htmlnano
as the last plugin:
var posthtml = require('posthtml');
var options = {
removeComments: false, // Disable the module "removeComments"
collapseWhitespace: 'conservative' // Pass options to the module "collapseWhitespace"
};
posthtml([
/* other PostHTML plugins */
require('htmlnano')(options)
]).process(html).then(function (result) {
// result.html is minified
});
// You can also use htmlnano modules separately:
posthtml([
require('htmlnano/lib/modules/mergeStyles').default
]).process(html);
By default all modules are enabled. You can disable some of them by passing module name with false
in the plugin options (like in the usage example above).
Collapses redundant white spaces (including new lines). It doesn’t affect white spaces in the elements <style>
, <textarea>
, <script>
, and <pre>
.
all
— collapses all redundant white spaces (default)conservative
— collapses all redundant white spaces to 1 space
<i>hello</i> <i>world</i>
after minification will be rendered as helloworld
.
To prevent that use conservative
option.
Source:
<div>
hello world!
<style>div { color: red; } </style>
</div>
Minified (with all
):
<div>hello world!<style>div { color: red; } </style></div>
Minified (with conservative
):
<div> hello world! <style>div { color: red; } </style> </div>
safe
– removes all HTML comments except the conditional comments and<!--noindex--><!--/noindex-->
(default)all
— removes all HTML comments
Source:
<div><!-- test --></div>
Minified:
<div></div>
Removes empty safe-to-remove attributes.
This module could break your styles or JS if you use selectors with attributes:
img[style=""] {
margin: 10px;
}
Source:
<img src="foo.jpg" alt="" style="">
Minified:
<img src="foo.jpg" alt="">
Minifies CSS with cssnano inside <style>
tags and style
attributes.
See the documentation of cssnano. For example you can keep outdated vendor prefixes:
htmlnano.process(html, {
minifyCss: {
autoprefixer: false
}
});
Source:
<div>
<style>
h1 {
margin: 10px 10px 10px 10px;
color: #ff0000;
}
</style>
</div>
Minified:
<div>
<style>h1{margin:10px;color:red}</style>
</div>
Minifies JS with UglifyJS2 inside <script>
tags.
See the API documentation of UglifyJS2
Source:
<div>
<script>
/* comment */
var foo = function () {
};
</script>
</div>
Minified:
<div>
<script>var foob=function(){};</script>
</div>
Minifies JSON inside <script type="application/json"></script>
.
Source:
<script type="application/json">
{
"user": "me"
}
</script>
Minified:
<script type="application/json">{"user":"me"}</script>
Minifies SVG inside <svg>
tags with SVGO.
Source:
<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="red" />
<circle cx="150" cy="100" r="80" fill="green" />
<text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>
</svg>`
Minified:
<svg width="300" height="200" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="red"/><circle cx="150" cy="100" r="80" fill="green"/><text x="150" y="125" font-size="60" text-anchor="middle" fill="#fff">SVG</text></svg>
Removes redundant attributes from tags if they contain default values:
method="get"
from<form>
type="text"
from<input>
type="submit"
from<button>
language="javascript"
andtype="text/javascript"
from<script>
charset
from<script>
if it's an external scriptmedia="all"
from<style>
and<link>
This module could break your styles or JS if you use selectors with attributes:
form[method="get"] {
color: red;
}
Source:
<form method="get">
<input type="text">
</form>
Minified:
<form>
<input>
</form>
Collapses boolean attributes (like disabled
) to the minimized form.
This module could break your styles or JS if you use selectors with attributes:
button[disabled="disabled"] {
color: red;
}
Source:
<button disabled="disabled">click</button>
<script defer=""></script>
Minified:
<button disabled>click</button>
<script defer></script>
Merges multiple <style>
with the same media
and type
into one tag.
<style scoped>...</style>
are skipped.
Source:
<style>h1 { color: red }</style>
<style media="print">div { color: blue }</style>
<style type="text/css" media="print">a {}</style>
<style>div { font-size: 20px }</style>
Minified:
<style>h1 { color: red } div { font-size: 20px }</style>
<style media="print">div { color: blue } a {}</style>
Merge multiple <script>
with the same attributes (id, class, type, async, defer
) into one (last) tag.
It could break your code if the tags with different attributes share the same variable scope. See the example below.
Source:
<script>var foo = 'A:1';</script>
<script class="test">foo = 'B:1';</script>
<script type="text/javascript">foo = 'A:2';</script>
<script defer>foo = 'C:1';</script>
<script>foo = 'A:3';</script>
<script defer="defer">foo = 'C:2';</script>
<script class="test" type="text/javascript">foo = 'B:2';</script>
Minified:
<script>var foo = 'A:1'; foo = 'A:2'; foo = 'A:3';</script>
<script defer="defer">foo = 'C:1'; foo = 'C:2';</script>
<script class="test" type="text/javascript">foo = 'B:1'; foo = 'B:2';</script>
It's also possible to pass custom modules in the minifier.
As a function:
var options = {
custom: function (tree, options) {
// Some minification
return tree;
}
};
Or as a list of functions:
var options = {
custom: [
function (tree, options) {
// Some minification
return tree;
},
function (tree, options) {
// Some other minification
return tree;
}
]
};
options
is an object with all options that were passed to the plugin.
Since the minifier is modular, it's very easy to add new modules:
-
Create a ES6-file inside
lib/modules/
with a function that does some minification. For example you can checklib/modules/example.es6
. -
Add the module in the modules array. The modules are applied from top to bottom. So you can choose the order for your module.
-
Create a JS-file inside
test/modules/
with some unit-tests. -
Describe your module in the section "Modules".
-
Send me a pull request.
Other types of contribution (bug fixes, documentation improves, etc) are also welcome! Would like to contribute, but don't have any ideas what to do? Check out our issues.