posthtml 默认不重构 html,因其核心仅解析、遍历和序列化节点树,所有重构逻辑必须通过显式 .use() 插件实现;常见错误是未加载插件导致输出与输入一致。

PostHTML 本身不提供“重构”能力,所有 HTML 自动化重构必须通过插件组合实现;直接调用 posthtml() 不会改变任何代码,必须显式 .use() 至少一个转换插件。
为什么 posthtml() 默认不重构 HTML?
PostHTML 核心只做三件事:解析 HTML 字符串为节点树(posthtml-parser)、遍历/修改树、再序列化回字符串。它不内置任何业务逻辑——没有自动闭合标签、不重排属性、不转换语义化标签,也不注入 class。所谓“重构”,全靠插件定义行为。
常见错误现象:posthtml().process(html) 返回的 result.html 和输入完全一致,开发者误以为“没生效”,其实是忘了 .use() 插件。
- 同步模式下必须用
sync: true配置才能配合同步插件,否则抛Promise is not resolved - 异步插件(如读取远程配置)不能混在同步流程里,否则
tree.walk()可能拿到未完成修改的节点 - 多个插件作用于同一节点时,执行顺序决定结果:后运行的插件可覆盖前者的
node.attrs或node.content
哪些插件能做典型 HTML 重构?
真正用于代码质量提升的插件,不是“美化”而是“修正”或“增强语义”。以下插件直接对应常见工程问题:
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
-
posthtml-urls:自动重写src/href路径,解决本地开发 vs 生产环境路径不一致问题 -
posthtml-include:把<include src="header.html"></include>替换为真实内容,替代手写拼接,避免重复模板 -
posthtml-expressions:支持<div title="{{title}}"> 这类轻量表达式,比引入完整模板引擎更轻量可控 <li> <code>posthtml-bem:自动将class="button primary"转为class="button button--primary",强制 BEM 规范落地 - 自定义插件中调用
node.tag = 'main'或delete node.attrs.id,可批量替换非语义化标签或清理冗余属性 - 永远先用
posthtml-parser单独测试输入 HTML 是否能被正确解析——含非法嵌套(如<p></p> <div></div>)或自闭合缺失(<img>vs<img>)会导致 AST 错乱 - 对
<script></script>和<style></style>节点默认跳过处理,除非插件明确声明支持(如posthtml-js),否则正则替换可能破坏 JS 字符串字面量 - 使用
posthtml-cli时加--dry-run参数(需插件支持)预览变更,或先输出到临时目录对比diff -r old/ new/ - 重构 class 名称时,注意 CSS 选择器兼容性:把
.card-title改成.card__title后,原有 CSS 若未同步更新,页面会丢失样式 - PHP 用
shell_exec('posthtml input.html -o output.html -p posthtml-bem')时,若插件依赖 Node.js 的fs.promises(Node ≥14),而服务器是 Node 12,会静默失败 - Webpack 的
html-loader+posthtml链路中,posthtml().process(content)的content是已由 webpack 解析过的字符串,可能已被转义(如"),插件若直接操作原始属性值会出错 - 全局安装的
posthtmlCLI 和项目本地node_modules中版本不一致,导致插件 API 行为变化(例如旧版posthtml-include不支持root选项)
如何安全地批量重构已有 HTML 文件?
重构不是“跑一次就完事”,尤其面对存量项目。关键在可逆性与边界控制:
PHP 或构建工具中调用 PostHTML 的坑
很多团队想在 PHP 后端或 Webpack 中嵌入 PostHTML,但忽略执行上下文差异:
最易被忽略的点:HTML 重构的成败不取决于插件多强大,而在于你能否准确定义“什么算重构完成”。是所有 div class="row" 都替换成 section?还是仅当它包裹了 article 时才替换?规则越模糊,插件越容易误伤。先写好匹配条件(比如用 tree.match({ tag: 'div', attrs: { class: /row/ } })),再动刀。










