#html #minify #html-parser #css #js #nodejs

minify-html

非常快且智能的HTML + JS + CSS压缩器

72个版本 (13个重大更新)

0.15.0 2023年12月24日
0.13.3 2023年12月24日
0.11.1 2023年5月7日
0.10.8 2023年1月31日
0.3.5 2020年7月30日

#5 in #minify

Download history 2946/week @ 2024-04-23 3165/week @ 2024-04-30 3159/week @ 2024-05-07 2884/week @ 2024-05-14 3166/week @ 2024-05-21 2889/week @ 2024-05-28 2775/week @ 2024-06-04 2989/week @ 2024-06-11 3361/week @ 2024-06-18 3073/week @ 2024-06-25 2485/week @ 2024-07-02 2988/week @ 2024-07-09 2992/week @ 2024-07-16 3445/week @ 2024-07-23 3571/week @ 2024-07-30 3377/week @ 2024-08-06

每月13,895次下载
31 个crate中使用了(28个直接使用)

MIT 协议

165KB
4K SLoC

minify-html

一个针对速度和效率精心优化的Rust HTML压缩器,并为其他语言提供绑定。

  • 高级压缩策略在速度上优于其他压缩器。
  • 使用SIMD搜索、直接尝试和查找表。
  • 处理无效HTML,经过广泛的测试和模糊测试
  • 使用minify-jslightningcss进行超快的JS和CSS压缩。

查看变更日志了解最新更新。

性能

html-minifierminimize的比较,在顶级网页上运行。在此处查看详细分解。

Chart showing speed of HTML minifiersChart showing compression of HTML minifiers

《onepass》变体在速度优化方面更为出色。有关详细信息,请参阅其README

兼容性和用法

命令行界面(CLI)

命令行工具名为minhtml。预编译的二进制文件适用于Linux(ARM64和x64)、macOS(ARM64和x64)和Windows(x64)。您可以在GitHub发行版中下载它们。

如果您已安装Cargo,也可以从源代码构建和安装:cargo install minhtml

使用

使用--help参数获取更多详细信息。

minhtml --output /path/to/output.min.html --keep-closing-tags --minify-css /path/to/src.html

就地并行处理多个文件

minhtml --keep-closing-tags --minify-css /path/to/**/*.html
Rust

获取

[dependencies]
minify-html = "0.15.0"

使用

查看API和使用示例的文档

Deno

使用

import init, {minify} from "https://wilsonl.in/minify-html/deno/0.15.0/index.js";

const encoder = new TextEncoder();
const decoder = new TextDecoder();

await init();

const minified = decoder.decode(minify(encoder.encode("<p>  Hello, world!  </p>"), { keep_spaces_between_attributes: true, keep_comments: true }));

所有Cfg字段都作为对象提供的第二个参数上的snake_case属性可用;如果未设置,则默认为false

Node.js
  • 包: @minify-html/node
  • 绑定: Neon
  • 平台:Linux(ARM64和x64)、macOS(ARM64和x64)、Windows(x64);Node.js 8.6.0及以上

获取

使用npm

npm i @minify-html/node

使用Yarn

yarn add @minify-html/node

使用

提供TypeScript定义。

import { Buffer } from "node:buffer";
import minifyHtml from "@minify-html/node";
// Or `const minifyHtml = require("@minify-html/node")` if not using TS/ESM.

const minified = minifyHtml.minify(Buffer.from("<p>  Hello, world!  </p>"), { keep_spaces_between_attributes: true, keep_comments: true });

所有Cfg字段都作为对象提供的第二个参数上的snake_case属性可用;如果未设置,则默认为false

Java
  • 包: in.wilsonl.minifyhtml
  • 绑定: JNI
  • 平台:Linux(ARM64和x64)、macOS(ARM64和x64)、Windows(x64);Java 7及以上

获取

作为Maven依赖项添加

<dependency>
  <groupId>in.wilsonl.minifyhtml</groupId>
  <artifactId>minify-html</artifactId>
  <version>0.15.0</version>
</dependency>

使用

import in.wilsonl.minifyhtml.Configuration;
import in.wilsonl.minifyhtml.MinifyHtml;

Configuration cfg = new Configuration.Builder()
    .setKeepHtmlAndHeadOpeningTags(true)
    .setMinifyCss(true)
    .build();

String minified = MinifyHtml.minify("<p>  Hello, world!  </p>", cfg);

所有Cfg字段都作为Builder上的camelCase设置方法可用;如果未设置,则默认为false

Python
  • 包: minify-html
  • 绑定: PyO3
  • 平台:Linux(ARM64和x64)、macOS(ARM64和x64)、Windows(x64);Python 3.8至3.12

获取

将PyPI项目作为依赖项添加,并使用pippipenv安装。

使用

import minify_html

minified = minify_html.minify("<p>  Hello, world!  </p>", minify_js=True, remove_processing_instructions=True)

所有Cfg字段都作为Python关键字参数可用;如果省略,则默认为False

Ruby
  • 包: minify_html
  • 绑定: rb-sysmagnus
  • 平台:Linux (ARM64 和 x64)、macOS (ARM64 和 x64)、Windows (x64);Ruby 2.7 到 3.2

获取

将库作为依赖项添加到 Gemfile*.gemspec

使用

require 'minify_html'

print minify_html("<p>  Hello, world!  </p>", { :keep_spaces_between_attributes => true, :minify_js => true })

所有 Cfg 字段 都是可用的;如果省略了任何字段,则默认为 false

WASM

可能需要 bundler 来使用 WebAssembly 模块,有关详细信息,请参阅 此处

使用

import init, {minify} from "@minify-html/wasm";

const encoder = new TextEncoder();
const decoder = new TextDecoder();

await init();

const minified = decoder.decode(minify(encoder.encode("<p>  Hello, world!  </p>"), { keep_spaces_between_attributes: true, keep_comments: true }));

所有Cfg字段都作为对象提供的第二个参数上的snake_case属性可用;如果未设置,则默认为false

模板语法

minify-html 可以解析和保留源代码中的 {{/{%/{#<% 语法,这允许压缩大多数引擎(如 Pebble、Mustache、Django、Go、Jinja、Twix、Nunjucks、Handlebars、Sailfish、JSP、EJS 和 ERB)编写的许多 HTML 模板。查找 preserve_*_template_syntax Cfg 选项。

PHP 块(<?php<?=)也是处理指令,默认情况下会被保留。

请注意,在这些语法中,解析是“愚蠢”的:它将简单地查找匹配闭合定界的下一个子序列字符。如果这些块内部出现嵌套或字符串字面量,可能会出现问题,但这种情况应该很少。

压缩

请注意,某些压缩操作可能会导致生成的 HTML 无法通过验证,但仍然可以由浏览器正确解释和渲染;基本上,利用了浏览器的宽松性以实现更好的压缩。要防止这种情况,请参考以下配置选项

  • do_not_minify_doctype
  • ensure_spec_compliant_unquoted_attribute_values
  • keep_spaces_between_attributes

空白

minify-html 具有高级上下文感知空白压缩功能,例如

  • precode 中保留空白,这些元素对空白敏感。
  • 在内容标签中修剪和合并空白,因为空白在渲染时总是会合并。
  • 在布局标签中删除空白,这允许使用内联布局同时保留格式化代码。

方法

有三种空白压缩方法。在处理文本内容时,minify-html 会根据包含元素选择使用哪种方法。

压缩空白

应用范围:任何元素,除了 对空白敏感 元素。

将文本节点中的空白字符序列减少为单个空格(U+0020)。

之前之后
<p>↵
··The·quick·brown·fox↵
··jumps·over·the·lazy↵
··dog.↵
</p>
<p>·The·quick·brown·fox·jumps·over·the·lazy·dog.·</p>
销毁整个空白

适用范围:除了以下元素以外的任何元素:空格敏感内容内容优先格式化元素。

删除标签之间的仅由空白字符组成的文本节点。

之前之后
<ul>↵
··<li>A</li>↵
··<li>B</li>↵
··<li>C</li></ul>
<ul>↵
··<li>A</li><li>B</li><li>C</li></ul>
去除空白

适用范围:除了以下元素以外的任何元素:空格敏感格式化元素。

删除标签的任何前导/尾部空白字符。

之前之后
<p>↵
··Hey,·I·<em>just</em>·found↵
··out·about·this·<strong>cool</strong>·website!↵
··<sup>[1]</sup></p>
<p>Hey,·I·<em>just</em>·found↵
··out·about·this·<strong>cool</strong>·website!↵
··<sup>[1]</sup></p>

元素类型

minify-html假定HTML和SVG元素按照标准和最佳实践进行使用。通过这些假设,它可以应用最优的空白最小化策略。如果这些假设不成立,请考虑调整HTML源代码或关闭空白最小化。

分组 元素 预期子元素
格式化 astrong其他元素 格式化元素,文本。
内容 h1p其他元素 格式化元素,文本。
布局 divul其他元素 布局元素,内容元素。
内容优先 labelli其他元素 类似于内容,但可能仅有一个子元素作为布局使用。
格式化元素

空白被折叠。

格式化元素通常是行内元素,它们围绕内容元素中的某些文本进行包裹,因此其空白不会像它们可能是内容的一部分那样被裁剪。

内容元素

空白被裁剪和折叠。

内容元素通常代表连续的完整内容单元,例如一个段落。因此,空白很重要,但空白序列最可能是由于格式化引起的。

之前
<p>↵
··Hey,·I·<em>just</em>·found↵
··out·about·this·<strong>cool</strong>·website!↵
··<sup>[1]</sup></p>
之后
<p>Hey,·I·<em>just</em>·found·out·about·this·<strong>cool</strong>·website!·<sup>[1]</sup></p>
布局元素

空白被裁剪和折叠。整个空白被删除。

这些元素应只包含其他元素,不包含文本。这使得删除整个空白成为可能,这在使用display: inline-block时很有用,这样元素之间的空白(例如缩进)就不会改变布局和样式。

之前
<ul>↵
··<li>A</li>↵
··<li>B</li>↵
··<li>C</li></ul>
之后
<ul><li>A</li><li>B</li><li>C</li></ul>
内容优先元素

空白被裁剪和折叠。

这些元素通常是内容元素,但偶尔也像只有一个子元素布局元素一样使用。整个空白不会被删除,因为它可能包含内容,但这是可以接受的,因为只有一个子元素,并且空白已被裁剪。

之前
<li>↵
··<article>↵
····<section></section>↵
····<section></section>↵
··</article></li>
之后
<li><article><section></section><section></section></article></li>

标签

删除可选的起始和结束标签

属性

解码属性值中的任何实体,然后计算并使用值的简短表示。

  • 双引号,任何"都被编码。
  • 单引号,任何'都被编码。
  • 未引用的字符串,如果适用,则第一个字符(如果是 "')后面的任何字符,以及任何空白字符都被编码。

属性在解码后会有空格被修剪和合并。

布尔属性 的值会被移除。如果 某些其他属性 的值为空或默认值,则这些属性会被完全移除。

如果 type 属性在 script 标签上的值等于一个 JavaScript MIME 类型,则该属性会被移除。

如果经过任何处理后属性值为空,则除了名称之外的所有内容都会被完全移除(即没有 =),因为空属性隐式地等同于具有空字符串值的属性。

在可能的情况下,会移除属性之间的空格。

实体

如果有效且解码后的长度较短或相等,则解码实体。较短的实体表示形式的 UTF-8 序列会被编码。

不引用有效 Unicode Scalar Value 的数值实体会被替换为 替换字符

在可能的情况下避免编码;例如,只有当 < 后跟一个有效的标签名字符时,才会对内容中的 < 进行编码。如果需要,会选择最短的实体表示形式。

注释

注释会被移除。

忽略

感叹号、处理指令 和空元素不会被移除,因为这假定它们的声明有特殊原因。

解析

minify-html 可以处理任何 HTML,优雅地处理所有可能的语法(包括无效的语法),就像浏览器一样。有关详细信息,请参阅 Parsing.md

问题和贡献

欢迎拉取请求和任何贡献!

如果 minify-html 做了意料之外的事情,误解了一些语法,或者错误地保留/删除了一些代码,请提出问题,并提供一些相关的代码,以便重现和调查问题。

依赖关系

~14MB
~196K SLoC