不能。PostHTML只做标准HTML/XML的AST解析,对未注册的自定义标签如<my-button>仅原样保留为普通节点,不触发任何行为,所有转换必须通过插件显式实现。

PostHTML 能不能直接解析未注册的自定义标签?
不能。PostHTML 本身只做标准 HTML/XML 的 AST 解析,posthtml-parser 对 <my-button>、<sql-query> 这类标签不会报错,但会原样保留为普通节点——它不关心语义,只按 HTML 规范建树。你看到的 tag: 'my-button' 是字符串值,不是可执行组件。
这意味着:如果你期望 <json-viewer json='{"a":1}'></json-viewer> 自动渲染成 <pre>...,PostHTML 不会帮你触发逻辑,它只负责把这行文本变成树上的一个对象。
- PostHTML 的作用边界很清晰:输入 HTML 字符串 → 输出 PostHTMLTree(JS 对象树)→ 插件修改树 → 输出新 HTML 字符串
- 所有“行为”必须显式写在插件里,比如用
tree.match({ tag: 'json-viewer' })拦截并替换节点 - 浏览器端的
customElements.define()和 PostHTML 无关;后者是构建时工具,前者是运行时机制
怎么用插件匹配并转换自定义标签?
核心是 tree.match() + 手动构造新节点。别试图复用 DOM API 或调用 innerHTML —— PostHTMLTree 是纯 JS 对象,没有浏览器环境。
例如把 <markdown>**hello**</markdown> 转成 <p><strong>hello</strong></p>:
立即学习“前端免费学习笔记(深入)”;
posthtml().use((tree) => {
return tree.match({ tag: 'markdown' }, (node) => {
const content = node.children?.[0]?.content || ''
// 假设你有轻量 markdown 解析器
const html = simpleMarkdown(content)
return { tag: 'p', children: [{ content: html }] }
})
})
-
tree.match()第一个参数支持对象匹配({ tag: 'xxx' })、正则(/^my-/)、函数((node) => node.tag?.startsWith('data-')) -
node.children是数组,可能为空;node.attrs是普通对象,属性值全是字符串,JSON 需手动JSON.parse(node.attrs.config) - 返回值必须是合法 PostHTML 节点结构:
{ tag, attrs, children },不能返回 DOM 元素或 React 组件
为什么 posthtml-loader 在 webpack 里常漏掉自定义标签?
根本原因是 loader 处理链顺序和资源类型判断出错。PostHTML 默认只处理 .html 文件内容,但很多项目里 html-webpack-plugin 或 raw-loader 已经提前把 HTML 当作字符串吞掉并输出到 bundle,posthtml-loader 根本没机会拿到原始 AST。
常见错误现象:Module parse failed: Unexpected token < 或插件里的 console.log 完全不触发。
- 确保
posthtml-loader在module.rules中排在html-webpack-plugin之前(它不参与 loader 链,所以得靠其他 loader 把 HTML 内容传进来) - 如果用
html-loader,必须开启preprocessor选项,并在里面调用posthtml().process(),且设sync: true - 检查文件是否被其他 loader 拦截:比如
/\.html$/规则被写成/\.htm$/,或test正则没覆盖到你的模板路径
自定义标签解析容易忽略的三个细节
多数人卡在“能跑通”,却在线上环境出问题。真正麻烦的不是语法,而是这些隐性约束:
- 嵌套自定义标签时,
tree.match()默认只匹配顶层节点;要递归处理,得在插件内部对node.children手动再调一次match或用tree.walk() - 属性名大小写敏感:
<MyTag data-foo="1">的node.attrs['data-foo']可取,但node.attrs['DATA-FOO']为空 —— 浏览器会小写化,PostHTML parser 也遵循此规则 - 空标签如
<img src="x">和自闭合自定义标签<my-img src="x"/>在 AST 中结构不同:node.tag === 'my-img'且node.content === undefined,但node.children为空数组,不是null
PostHTML 不是黑盒,它的 AST 结构透明但严格;自定义标签处理的关键,从来不是“怎么让它工作”,而是“怎么让它在各种嵌套、大小写、空标签场景下依然稳定”。



















