PostHTML 是基于 AST 的 HTML 转换器,通过解析→修改 AST→生成新 HTML 实现结构重写;需配合插件、规则精准才能生效,不支持运行时逻辑,也不保留默认格式。

PostHTML 是什么,它真能改 HTML 结构?
PostHTML 不是模板引擎,也不是构建工具插件;它是一个基于 AST 的 HTML 转换器,核心能力就是「解析 → 修改 AST → 生成新 HTML」。你写规则,它按规则重写标签、属性、文本甚至注释。能自动化转换结构,但前提是规则写得准——它不会猜你想要什么。
常见错误现象:posthtml() 执行后 HTML 完全没变,或只改了部分节点。原因通常是插件没返回修改后的 node,或者选择器写错了(比如用 div.class 匹配自闭合标签)。
- PostHTML 本身不带任何转换逻辑,必须配合插件(如
posthtml-extend、posthtml-modules)或手写插件 - 所有操作都发生在 AST 层,原始缩进、注释、空格默认不保留(需额外配置
sync: true或用posthtml-render控制输出) - 不支持运行时逻辑(比如 if/else 渲染),纯静态结构变换
怎么写一个最简插件来替换 <img> 标签?
这是最典型的结构转换场景:把 <img src="a.jpg"> 换成 <picture><source><img></picture>。关键不是套用现成插件,而是理解插件函数的输入输出契约。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 插件函数接收
tree(AST 根节点),必须遍历并修改其children数组中的node - 匹配
<img>用node.tag === 'img',别依赖正则或字符串查找 - 新建节点必须用
{ tag: 'picture', children: [...] }这种对象结构,不能拼 HTML 字符串 - 原
node必须从父节点children中移除,再 push 新结构,否则会重复渲染
示例片段:
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
posthtml([function () {
return function (tree) {
tree.match({ tag: 'img' }, (node) => {
const src = node.attrs?.src
return {
tag: 'picture',
children: [
{ tag: 'source', attrs: { srcset: src } },
{ ...node } // 复用原 img 节点,避免丢失 alt/class 等
]
}
})
}
}])
为什么 posthtml-loader 在 webpack 里经常不生效?
根本原因是 loader 链顺序和资源类型判断。PostHTML 默认只处理 .html 文件,而 posthtml-loader 若放在 html-webpack-plugin 之后,或被 raw-loader / file-loader 提前截走,就根本收不到 AST。
常见错误现象:Module parse failed: Unexpected token <,或插件日志完全没打印。
- 确保
posthtml-loader在webpack.config.js的module.rules中排在其他 HTML 处理 loader 之前 - 检查
test正则是否覆盖目标文件,比如/\.html$/不会匹配index.ejs - 若用
html-webpack-plugin注入模板,要传template: './src/index.html',而不是直接写字符串 - 调试技巧:在插件函数开头加
console.log(tree),确认是否进入;若没输出,说明 loader 根本没触发
如何安全地批量重命名 class 名?
用 PostHTML 做 CSS BEM 转换或 scope 化时,不能只改 class 属性值,还要同步处理 className(JSX)、class 在 style 标签内、甚至内联 data-class——这些 PostHTML 默认不碰。它只管 HTML 标签树。
所以「安全」的关键是限定范围 + 明确边界:
- 只处理
node.attrs.class,别碰node.content(里面可能是 JS 代码或 CSS) - 用
node.attrs.class.split(' ').map(...).join(' ')拆分处理,避免正则误替换class="foo-bar"中的bar - 若项目混用 Pug/Vue/Svelte,PostHTML 无法解析它们的模板语法,必须先编译成标准 HTML 再处理
- 性能提示:大量 class 替换建议用
tree.walk一次遍历,别对每个节点反复调用tree.match
容易被忽略的一点:PostHTML 不校验 HTML 合法性。如果原始 HTML 有未闭合标签(比如 <div><p>),AST 可能错乱,导致 class 替换漏掉某些节点——务必先用 posthtml-parser 的严格模式或预处理校验。


















