posthtml 不是模板引擎或构建工具内置功能,它仅将 html 转为 ast、供修改后再转回 html;若调用 posthtml() 后无变化,主因是插件未返回新节点或匹配条件错误,且标签名大小写敏感、自闭合标签无 children,多插件需注意执行顺序,webpack 中需确保 posthtml-loader 置于 html-loader 的 postprocessor 内而非独立 rule。

PostHTML 不是模板引擎,也不是构建工具内置功能;它只做一件事:把 HTML 变成 AST、让你改、再变回 HTML。想靠它实现运行时逻辑或自动补全结构,会直接掉坑里。
posthtml() 调用后 HTML 完全没变,怎么回事?
最常见原因是插件函数没返回新节点,或者匹配条件写错。PostHTML 不会“自动生效”,它只执行你明确返回的替换逻辑。
-
tree.match()里的回调必须返回一个新节点对象(如{ tag: 'div', children: [...] }),返回undefined或原封不动的node就等于没改 - 匹配
<img>不能写node.tag === 'IMG'—— 标签名大小写敏感,一律小写 - 自闭合标签(如
<img>、<meta>)不带children,别在插件里对node.children.push()硬操作,会报错 - 如果用了多个插件,注意执行顺序:后一个插件看到的是前一个改完的 AST,不是原始 HTML
webpack 里 posthtml-loader 不生效,怎么排?
根本不是插件写得不对,而是 loader 链被截断了。PostHTML 默认只处理字符串内容,如果 html-loader 之前有 raw-loader 或 file-loader 先吞掉了 HTML 文件,posthtml-loader 根本收不到输入。
-
posthtml-loader必须放在html-loader的options.postprocessor里,而不是单独写一条use规则 - 确保
test: /\.html$/的 rule 中,只有html-loader在处理,其他 loader(比如file-loader)的test不能覆盖 .html - 调试时加个
console.log在插件函数开头,如果日志不打印,说明 loader 根本没走到这一步
怎么安全地把
换成 ?
核心是复用原节点,而不是拼字符串。手动拼 '<picture><source srcset="' + src + '"><img ...></source></picture>' 会丢属性、破坏嵌套、绕过 AST 校验。
- 用
node.attrs?.src取值,别假设attrs一定存在 - 新
picture节点的children数组里,直接放{ tag: 'source', attrs: { srcset: src } }和node(原img对象),这样alt、class、loading全都保留 - 不要在遍历中直接修改
tree.children,要用tree.match()提供的机制,否则可能漏节点或重复处理
真正难的不是写插件,而是判断哪些结构该进 AST、哪些该交给构建工具其他环节处理。比如路径重写该由 html-loader 做,图片格式转换才轮到 posthtml-webp —— 混用层级,比写错一个 node.tag 更容易引发连锁失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











