Presets
A preset is just an object with modules config.
Currently the following presets are available:
- safe — default preset for safe minification.
- ampSafe — same as
safebut tailored for AMP pages. - max — maximal minification (might break some pages).
safe compatibility contract
safe preserves browser-parsed HTML behavior, not the original source. It may
simplify syntax and remove empty or redundant whitespace when the result parses
as an equivalent HTML document or fragment.
It does not guarantee preservation of outerHTML, attribute presence or order,
comments removed by removeComments: 'safe', or XHTML/XML serialization.
ampSafe follows the same contract while keeping the output valid AMP HTML.
For optional tags, safe uses
removeOptionalTags: { removeStartTags: false }: it retains every explicit
start tag while omitting eligible end tags. ampSafe inherits this conservative
setting. max uses removeOptionalTags: true, so it may omit eligible start
tags as well as end tags.
The completed preset changes differ as follows:
| Behavior | safe | ampSafe | max |
|---|---|---|---|
| Attribute quotes | Removes optional quotes | Same as safe | Removes optional quotes |
| Optional tags | End tags only | End tags only | Start and end tags |
| Doctype normalization | Short HTML5 doctypes only | Short HTML5 doctypes only | Broad, including legacy doctypes |
| IE conditional comments | Unchanged | Unchanged | Minifies their contents |
| Attribute sorting | Disabled | Disabled | Alphabetical |
ampSafe otherwise differs from safe by enabling AMP-specific boolean
attribute collapsing and disabling JavaScript minification. Attribute sorting
remains out of both safe presets because measurements on the cached benchmark
corpus showed that it increased gzip and Brotli sizes despite leaving raw size
unchanged.
max enables lossy modules on purpose. The most visible one is
removeEmptyElements with
removeWithAttributes: 'presentational': empty elements whose attributes are all
presentational (class, style, aria-hidden) are dropped, which removes
purely decorative markup such as carousel dots, skeleton loaders and spacers.
Elements with an id, a role, data-*, event handlers and the like are kept,
as are <canvas>, <slot>, <iframe>, custom elements and interactive elements
such as <button> and <a>. Removal keeps the meaning and accessibility of the
page intact, but class is also a scripting hook, so a decorative element that
some script looks up by class will no longer be found. If you want those
decorations back, override the module:
htmlnano.process(html, { removeEmptyElements: true }, htmlnano.presets.max);
max also configures minifyJs with format: { comments: false }, which drops the
@license/@preserve//*! comments Terser keeps by default. That is a legal trade-off — most JS licenses
require the notice to be distributed with the code — so only use it when the notices are shipped elsewhere.
To keep them:
htmlnano.process(html, { minifyJs: { format: { comments: 'some' } } }, htmlnano.presets.max);
You can use them the following way:
const htmlnano = require('htmlnano');
const ampSafePreset = require('htmlnano').presets.ampSafe;
htmlnano.process(html, { collapseWhitespace: 'conservative' }, ampSafePreset)
.then((result) => {
// result.html is minified
})
.catch((err) => {
console.error(err);
});
You can also import presets directly:
import htmlnano from 'htmlnano';
import ampSafe from 'htmlnano/presets/ampSafe';
const result = await htmlnano.process(html, {}, ampSafe);
If you skip preset argument, safe is 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 your own presets by starting from a built-in one:
const htmlnano = require('htmlnano');
const emailPreset = {
...htmlnano.presets.safe,
mergeStyles: true,
minifyCss: {
safe: true
}
};
htmlnano.process(html, { removeComments: false }, emailPreset)
.then((result) => {
// result.html is minified
})
.catch((err) => {
console.error(err);
});
Feel free to submit a PR with your preset if it might be useful for other developers as well.