html-validate 必须在构建阶段前置执行以拦截 HTML 结构性错误,否则浏览器静默修正将导致 DOM 行为异常且运行时无法修复;Webpack 和 Vite 均需在生产构建前集成校验,CI 中严禁忽略退出码,且须自定义 element-permitted-content 规则。

构建阶段必须拦截 HTML 结构性错误,否则上线后 DOM 行为不可控——document.querySelector('p').children 返回空数组、table 渲染缺 tbody、img 闭合失败导致后续节点错位,全是浏览器静默修正惹的祸,运行时 JS 无法修复。
html-validate 必须跑在构建命令之前
它不是 CI 后期“扫尾工具”,而是防止结构污染的第一道闸门。一旦错误 HTML 进入 dist 目录或仓库,修复成本指数级上升。
- Webpack:在
webpack --mode production前加npx html-validate src/**/*.html --config .htmlvalidate.json,失败则中断构建 - Vite:在
npm run build脚本中前置执行npx html-validate src/index.html src/pages/**/*.html - CI 中禁止用
|| true忽略 html-validate 退出码,否则等于没开
element-permitted-content 规则必须自定义
默认规则对 p、li、td 等容器过于宽松,放行 <p></p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill9263" title="Html2md"><img
src="https://img.php.cn/upload/skill/000/000/081/179249945220127.jpg" alt="Html2md" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill9263" title="Html2md">Html2md</a>
<p>使用 Readability + Turndown 将 HTML 页面转换为干净的、Agent 友好的 Markdown。去除导航栏、广告、页脚、Cookie 横幅、社交按钮等干扰元素。支持 URL...</p>
</div>
<a href="/xiazai/skill9263" title="Html2md" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div>
<div>xxx</div>
<p></p><div>xxx</div><p></p>。
- 在
.htmlvalidate.json中显式声明:"element-permitted-content": {"p": ["#text", "br", "span", "em", "strong"]} - 对
li禁止直接子元素为div,只允许ol/ul/div(需确认是否语义合理) - 检查
table是否强制要求thead/tbody,避免仅靠 CSS 隐藏却未声明结构
html-webpack-plugin / vite-plugin-html 的注入逻辑会污染结构
插件自动注入 <script> 或变量时,若位置非法(比如插到 <head> 里紧挨着 <main> 开头),会触发浏览器重排并破坏父子关系。
立即学习“前端免费学习笔记(深入)”;
- Vite 中模板变量写法必须是
<%= VITE_API_BASE %>,写成%VITE_API_BASE%会导致字符串残留,被当作文本节点插入 - Webpack 下若用
html-loader处理含<script type="module">的片段,import会被当普通字符串,引发ReferenceError: require is not defined - 多页应用必须为每个页面配独立
HtmlWebpackPlugin实例,并显式指定chunks,否则 login 页面可能加载 dashboard 的 JS,触发非预期 DOM 操作
最易被忽略的是:VS Code 缩进视觉正常 ≠ 结构合法。<p><div>xxx</div></p> 在编辑器里看着是嵌套,Elements 面板里实际是断裂的同级节点——这个差异只有在构建前用 html-validate + 自定义规则才能捕获。


















