默认htmllint规则仅覆盖w3c合规性等通用项,无法拦截业务级隐患(如缺失data-testid、空alt未强制存在、禁止onclick等),须手动配置.htmllintrc启用或自定义规则;eslint-plugin-html则用于补充js模板逻辑层检查,二者需配合使用。

HTML 代码里的隐患,光靠肉眼和基础校验很难挖出来;真正能系统性排查的,是可定制规则的 htmllint 或 eslint-plugin-html,而不是默认开箱即用的检查器。
为什么默认 htmllint 规则拦不住业务级隐患
默认配置只覆盖 W3C 合规性、基础标签嵌套、属性拼写等通用项,比如 attr-value-not-empty 或 id-unique。但团队内部的隐患往往藏在语义约定里:比如所有按钮必须带 data-testid,所有图片必须有 alt(哪怕为空),或者禁止在 <div> 上直接写 <code>onclick —— 这些规则默认关闭,不手动启用或自定义就完全失效。
常见错误现象包括:
- CI 流水线通过了,但测试环境发现大量缺失
data-testid,导致 E2E 脚本批量失败 - 上线后被无障碍审计工具报出 80% 的
<img>缺少alt,却没在本地 lint 阶段暴露 -
htmllint报了一堆attr-no-duplication,但没人意识到这是因为构建时模板引擎重复注入了同一属性
如何用 htmllint 配置文件精准拦截特定隐患
关键不是堆规则,而是让每条规则对应一个可验证、可归责的业务约束。配置入口是 .htmllintrc,它支持 JSON/YAML/JS 格式,推荐用 JS 以便加注释和条件逻辑。
实操建议:
- 把高危模式单独拎成一条规则,例如禁止内联事件处理器:
{"tag-req-attr": ["button", ["data-testid"]], "attr-ban-list": ["onclick", "onchange", "onsubmit"]} - 对空
alt放行但强制存在,用attr-req-value配合正则:{"attr-req-value": [{"tag": "img", "attr": "alt", "value": ".*"}]} - 避免全局污染,用
ignore字段排除构建产物目录(如dist/、build/),否则会误报打包后生成的 HTML - 性能敏感项目可关掉 DOM 深度遍历类规则(如
head-script-disabled),改用更轻量的行级规则组合
当 htmllint 不够用:用 eslint-plugin-html 补业务逻辑层
htmllint 只看 HTML 结构,没法感知 JS 变量是否被正确注入到模板中。比如 EJS 或 Vue SFC 中的 ,若 user 为 null,HTML 层无异常,但运行时炸了——这种隐患得靠 eslint-plugin-html 把 HTML 当 JS 字符串扫描。
使用场景:
- 检查模板字符串中是否用了未声明变量:
eslint . --ext .html,.ejs --rules '{"html/no-unescaped-entity": "error"}' - 配合
eslint-plugin-react检查 JSX 中的 HTML 属性合法性(如class应为className) - 在
.eslintrc.js中启用overrides,只为**/*.html启用html/*规则,避免干扰 JS 文件
注意:eslint-plugin-html 依赖 ESLint v8.50+,旧版会跳过 HTML 文件解析;且它不校验 HTML 语法本身,必须和 htmllint 配合使用才完整。
容易被忽略的集成盲区
最常被跳过的不是规则怎么写,而是「谁在什么时候触发检查」。很多团队只在 pre-commit 本地跑,但忽略了三个关键节点:
- 编辑器实时提示没配
htmllint的 Language Server(如 VS Code 的htmllint-server插件),导致问题拖到提交才暴露 - CI 中没锁定
htmllint版本,某次npm install升级后规则行为突变(比如 v3.0 开始默认开启attr-no-unsafe-char) - 忽略 HTML 和构建工具的耦合点:Webpack 的
html-webpack-plugin注入的script标签,可能绕过htmllint扫描范围,需额外配置filesglob 匹配输出目录
真正起作用的定制化,从来不在规则数量,而在每条规则是否绑定到一个明确的故障场景、责任人和拦截时机。











