PostHTML插件必须显式传入posthtml([])数组才生效,否则被忽略;常见错误是漏写方括号或未按顺序配置(如posthtml-include须在posthtml-minifier前),且需正确设置root、extensions等选项避免路径解析失败。
PostHTML 默认不自动执行插件,posthtml() 调用时必须显式传入插件数组,否则所有配置形同虚设。常见错误是只写了插件导入却没放进 plugins 选项里,或者误把插件函数直接当参数传(漏了 [])。
posthtml([require('posthtml-include'), require('posthtml-minifier')])
posthtml(require('posthtml-include'))(会报 TypeError: plugin is not a function)posthtml-include 必须在 posthtml-minifier 前,否则 include 还没展开就被压缩,导致路径失效posthtml-include 默认基于当前工作目录解析 src,不是相对于被包含文件的位置。很多项目结构嵌套深,一写 <include src="header.html"></include> 就报 ENOTDIR 或 ENOENT。
root 选项,比如 { root: path.resolve(__dirname, 'src') }
src="../components/footer.html" 是相对于调用 <include> 的文件所在目录,不是 root
.htm 或无后缀文件,得加 extensions: ['.html', '.htm']
posthtml-minifier 默认启用 collapseWhitespace 和 removeComments,但某些内联 <script> 或 <style> 里有依赖空白或注释的逻辑(比如 CSS hack、模板字符串换行),会被破坏。
{ collapseWhitespace: false, removeComments: false }
posthtml-expressions 或 posthtml-modules 把逻辑外移,避免压缩干扰posthtml-minifier 不处理外部资源,JS/CSS 文件需单独走 Webpack/Vite 构建流程,别指望它替你压缩 <script src="app.js"></script>
PostHTML 插件默认是同步的,但读取远程模板、调用 API、解析 YAML Front Matter 等场景需要异步。直接 return Promise 不生效,必须用 async/await + 正确的插件签名。
立即学习“前端免费学习笔记(深入)”;
async 函数要包裹在 tree 回调中:module.exports = async (tree) => { const data = await fetch(...); tree.match({ tag: 'blog' }, ...); }
await 后修改 tree 却不调用 tree.match 或 tree.walk —— PostHTML 不会等待你的 Promiseconsole.log('running'),确认是否被调用;再加 console.log(await someAsync()) 看是否卡住PostHTML 的链式处理很轻量,但每个插件的执行时机和上下文边界容易模糊。最常被忽略的是:插件之间不共享状态,tree 是只读副本,想跨插件传数据得靠 tree.metadata 或外部变量缓存 —— 而这恰恰是调试时最难定位的问题来源。