推荐用 html-validate + git hooks 组合实现本地提交前自动检查html语义错误,如缺标题、重复、缺alt等,通过 husky 绑定 pre-commit 钩子并仅扫描本次改动文件,兼顾准确性与性能。

本地提交前怎么自动检查HTML语义错误
Git commit 触发时必须拦住 <section></section> 缺标题、<main></main> 重复、<img> 缺 alt 这类硬性语义缺陷,不能靠人工 Review 记住所有规则。
推荐用 html-validate + Git hooks 组合,它比 W3C Validator 更适合工程化集成,能直接读取 ESLint 风格的配置。
- 安装:
npm install --save-dev html-validate - 加配置文件
.htmlvalidate.json,启用关键规则:"require-title": "error"、"require-alt-attribute": "error"、"no-duplicate-id": "error" - 在
package.json的scripts中加:"validate:html": "html-validate src/**/*.html" - 用
husky绑定 pre-commit:npx husky add .husky/pre-commit "npm run validate:html"
注意:如果项目含大量遗留模板(如 CMS 输出),可先设为 warn 级别,但上线前必须升为 error;<section></section> 没 <h2></h2> 到 <h6></h6> 会被直接拒绝提交,不是警告。
为什么 htmlhint 在本地卡点容易失效
htmlhint 默认不校验语义结构,只查基础语法(比如标签闭合、引号缺失),对 <nav></nav> 里塞搜索框、<aside></aside> 包广告这类逻辑错误完全无感——它把 HTML 当纯文本扫,不是 DOM 结构分析器。
常见失效场景:
- 配置了
"attr-lowercase": true,但漏掉"heading-level"规则,导致标题跳级(<h1></h1>后直接<h4></h4>)逃过检查 - 没启用
"id-class-value": "dash",class="userProfileCard"这种驼峰命名不会报错,但后续 CSS 或 JS 工具链可能出兼容问题 - VS Code 插件开启自动校验,但 CLI 命令行跑
htmlhint时未加载同一份配置,本地和 CI 结果不一致
结论:仅用 htmlhint 做卡点,等于只守住了 HTML 的“拼写”,没管“语法”和“语义”。
如何让本地卡点不拖慢开发节奏
全量扫描整个 src/ 目录下所有 HTML 文件,一次要 3–5 秒,开发者等不起。必须只检本次改动部分。
实操方案:
- 用
git diff --cached --name-only --diff-filter=ACM | grep '\.html$'提取本次 commit 新增/修改的 HTML 文件路径 - 把路径传给
html-validate:html-validate $(git diff --cached --name-only --diff-filter=ACM | grep '\.html$') - 加到 husky pre-commit 脚本里,避免扫描未改动文件
- 若某次提交含 10 个 HTML 文件,平均耗时压到 300ms 内;单文件修改基本感知不到延迟
额外提醒:不要在 pre-push 阶段补这个检查——push 前才暴露问题,修复成本远高于 commit 前。
<main></main> 多次出现为什么必须卡死
浏览器只认第一个 <main></main>,其余被忽略;屏幕阅读器会直接跳过后续 <main></main> 里的内容,等于功能不可达——这不是样式错位,是残障用户根本无法操作。
容易踩的坑:
- 组件化开发中,每个 Vue/React 组件自带
<main></main>,拼接后页面出现多个 - SSR 模板里
<main></main>写在 layout,但子页面又自己加一个 - 用
innerHTML动态插入 HTML 片段时,片段内含<main></main>,导致运行时 DOM 出现重复
真正难的是发现时机:只有在完整 HTML 字符串生成后才能判断,所以静态扫描工具(如 html-validate)必须作用于最终输出文件,而非源组件文件。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











