
Product
Secure Your AI-Generated Code with Socket MCP
Socket MCP brings real-time security checks to AI-generated code, helping developers catch risky dependencies before they enter the codebase.
htmlnano is a highly configurable HTML minifier that helps reduce the size of HTML files by removing unnecessary characters, comments, and whitespace. It also provides various optimization options to improve the performance of web pages.
Minification
This feature removes unnecessary characters, comments, and whitespace from HTML files to reduce their size.
const htmlnano = require('htmlnano');
const html = '<!DOCTYPE html> <html> <head> <title>Test</title> </head> <body> <h1>Hello, world!</h1> </body> </html>';
htmlnano.process(html).then(result => console.log(result.html));
Attribute Optimization
This feature removes empty attributes from HTML tags to further reduce the file size.
const htmlnano = require('htmlnano');
const html = '<img src="image.jpg" alt="" />';
const options = { removeEmptyAttributes: true };
htmlnano.process(html, options).then(result => console.log(result.html));
CSS and JS Minification
This feature minifies inline CSS and JavaScript within HTML files to optimize performance.
const htmlnano = require('htmlnano');
const html = '<style>body { margin: 0; }</style><script>console.log("Hello, world!");</script>';
const options = { minifyCss: true, minifyJs: true };
htmlnano.process(html, options).then(result => console.log(result.html));
Removing Redundant Attributes
This feature removes redundant attributes from HTML tags to make the HTML cleaner and smaller.
const htmlnano = require('htmlnano');
const html = '<input type="text" disabled="disabled" />';
const options = { removeRedundantAttributes: true };
htmlnano.process(html, options).then(result => console.log(result.html));
html-minifier is a popular HTML minification tool that offers a wide range of options for compressing HTML files. It is highly configurable and can remove comments, whitespace, and redundant attributes, similar to htmlnano. However, html-minifier is more widely used and has a larger community.
clean-css is a fast and efficient CSS minifier that can be used to minify inline CSS within HTML files. While it focuses solely on CSS, it can be used in conjunction with other tools to achieve similar results to htmlnano's CSS minification feature.
terser is a JavaScript minifier that can be used to minify inline JavaScript within HTML files. It is highly configurable and offers advanced options for compressing and optimizing JavaScript code. When used alongside other tools, it can provide similar functionality to htmlnano's JS minification feature.
Modular HTML minifier, built on top of the PostHTML. Inspired by cssnano.
The author of htmlnano is available for hire as a full stack web developer: https://kirillmaltsev.net/services
Website | Source (KB) | html-minifier@3.5.20 | htmlnano@0.2.0 |
---|---|---|---|
stackoverflow.com | 258 | 205 | 218 |
github.com | 63 | 51 | 56 |
en.wikipedia.org | 77 | 69 | 74 |
npmjs.com | 32 | 29 | 30 |
Avg. minify rate | 0% | 15% | 9% |
npm install --save-dev gulp-htmlnano
const gulp = require('gulp');
const htmlnano = require('gulp-htmlnano');
const options = {
removeComments: false
};
gulp.task('default', function() {
return gulp
.src('./index.html')
.pipe(htmlnano(options))
.pipe(gulp.dest('./build'));
});
const htmlnano = require('htmlnano');
const options = {
removeEmptyAttributes: false, // Disable the module "removeEmptyAttributes"
collapseWhitespace: 'conservative' // Pass options to the module "collapseWhitespace"
};
htmlnano
// "preset" arg might be skipped (see "Presets" section below for more info)
.process(html, options, preset)
.then(function (result) {
// result.html is minified
})
.catch(function (err) {
console.error(err);
});
Just add htmlnano
as a final plugin:
const posthtml = require('posthtml');
const options = {
removeComments: false, // Disable the module "removeComments"
collapseWhitespace: 'conservative' // Pass options to the module "collapseWhitespace"
};
const posthtmlPlugins = [
/* other PostHTML plugins */
require('htmlnano')(options)
];
posthtml(posthtmlPlugins)
.process(html)
.then(function (result) {
// result.html is minified
})
.catch(function (err) {
console.error(err);
});
A preset is just an object with modules config.
Currently the following presets are available:
safe
preset but for AMP pagesYou can use them the following way:
const htmlnano = require('htmlnano');
const ampSafePreset = require('htmlnano').presets.ampSafe;
const options = {
// Your options
};
htmlnano
.process(html, options, ampSafePreset)
.then(function (result) {
// result.html is minified
})
.catch(function (err) {
console.error(err);
});
If you skip preset
argument safe
preset would be used by default.
If you'd like to define your very own config without any presets pass an empty object as a preset:
const htmlnano = require('htmlnano');
const options = {
// Your options
};
htmlnano
.process(html, options, {})
.then(function (result) {
// result.html is minified
})
.catch(function (err) {
console.error(err);
});
You might create also your own presets:
const htmlnano = require('htmlnano');
// Preset for minifying email templates
const emailPreset = {
mergeStyles: true,
minifyCss: {
safe: true
},
};
const options = {
// Some specific options
};
htmlnano
.process(html, options, emailPreset)
.then(function (result) {
// result.html is minified
})
.catch(function (err) {
console.error(err);
});
Feel free to submit a PR with your preset if it might be useful for other developers as well.
By default the modules should only perform safe transforms, see the module documentation below for details.
You can disable modules by passing false
as option, and enable them by passing true
.
Collapse redundant white spaces in list-like attributes (class
, rel
, ping
).
Source:
<div class=" content page "></div>
Minified:
<div class="content page"></div>
Collapses redundant white spaces (including new lines). It doesn’t affect white spaces in the elements <style>
, <textarea>
, <script>
and <pre>
.
conservative
— collapses all redundant white spaces to 1 space (default)all
— collapses all redundant white spaces<i>hello</i> <i>world</i>
after minification will be rendered as helloworld
.
To prevent that use conservative
option (this is the default 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>
Remove duplicate values from list-like attributes (class
, rel
, ping
).
Source:
<div class="sidebar left sidebar"></div>
Minified:
<div class="sidebar left"></div>
safe
– removes all HTML comments except the conditional comments and <!--noindex--><!--/noindex-->
(default)all
— removes all HTML commentsSource:
<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="">
Removes unused CSS inside <style>
tags with either uncss
or PurgeCSS.
See the documentation of uncss for all supported options.
uncss options can be passed directly to the removeUnusedCss
module:
htmlnano.process(html, {
removeUnusedCss: {
ignore: ['.do-not-remove']
}
});
The following uncss options are ignored if passed to the module:
stylesheets
ignoreSheets
raw
Use PurgeCSS instead of uncss by adding tool: 'purgeCSS'
to the options.
See the documentation of PurgeCSS for all supported options.
PurgeCSS options can be passed directly to the removeUnusedCss
module:
htmlnano.process(html, {
removeUnusedCss: {
tool: 'purgeCSS',
whitelist: ['.do-not-remove']
}
});
The following PurgeCSS options are ignored if passed to the module:
content
css
extractors
Source:
<div class="b">
<style>
.a {
margin: 10px 10px 10px 10px;
}
.b {
color: #ff0000;
}
</style>
</div>
Optimized:
<div class="b">
<style>
.b {
color: #ff0000;
}
</style>
</div>
Minifies CSS with cssnano inside <style>
tags and style
attributes.
See the documentation of cssnano for all supported optimizations.
By default CSS is minified with preset default
, which shouldn't have any side-effects.
To use another preset or disabled some optimizations pass options to minifyCss
module:
htmlnano.process(html, {
minifyCss: {
preset: ['default', {
discardComments: {
removeAll: true,
},
}]
}
});
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 using Terser inside <script>
tags.
See the documentation of Terser for all supported options.
Terser options can be passed directly to the minifyJs
module:
htmlnano.process(html, {
minifyJs: {
output: { quote_style: 1 },
},
});
Source:
<div>
<script>
/* comment */
const foo = function () {
};
</script>
</div>
Minified:
<div>
<script>const foo=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 using SVGO.
See the documentation of SVGO for all supported options.
SVGO options can be passed directly to the minifySvg
module:
htmlnano.process(html, {
minifySvg: {
plugins: [
{ collapseGroups: false },
],
},
});
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 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="#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"
and type="text/javascript"
from <script>
charset
from <script>
if it's an external scriptmedia="all"
from <style>
and <link>
This module is disabled by default, change option to true to enable this module.
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.
If your document uses AMP, set the amphtml
flag
to collapse additonal, AMP-specific boolean attributes:
"collapseBooleanAttributes": {
"amphtml": true
}
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>const 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>const 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:
const options = {
custom: function (tree, options) {
// Some minification
return tree;
}
};
Or as a list of functions:
const 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 check lib/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.
[0.2.5] - 2019-11-09
FAQs
Modular HTML minifier, built on top of the PostHTML
The npm package htmlnano receives a total of 365,980 weekly downloads. As such, htmlnano popularity was classified as popular.
We found that htmlnano demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket MCP brings real-time security checks to AI-generated code, helping developers catch risky dependencies before they enter the codebase.
Security News
As vulnerability data bottlenecks grow, the federal government is formally investigating NIST’s handling of the National Vulnerability Database.
Research
Security News
Socket’s Threat Research Team has uncovered 60 npm packages using post-install scripts to silently exfiltrate hostnames, IP addresses, DNS servers, and user directories to a Discord-controlled endpoint.