HTMLHint必须在模板渲染完成、HTML文件写入磁盘前介入,对内存中renderedHtml字符串实时校验;它不替代Prettier,专查语义、可访问性与SEO问题,如alt缺失、标题唯一性、属性重复等,且需统一CI与本地版本以避免解析差异。

HTMLHint 必须在模板渲染后、写入磁盘前介入
静态站点生成器(如 Eleventy、Astro、Hugo)输出 HTML 的那一刻,就是质量失控风险最高的窗口。等文件落地再扫描,修复成本翻倍,CI 里报错也难定位到具体模板行。真正有效的控制点,是拿到内存中刚渲染完的 renderedHtml 字符串,立刻校验。
常见错误现象:htmlhint ./dist/**/*.html 在 CI 里报一堆 Attribute "class" is not allowed on element "img",但本地不报——其实不是 HTML 错,是规则没适配现代标准,或 CI 环境用了旧版 HTMLHint 解析器。
- Eleventy:在
eleventyConfig.addTransform中拦截输出字符串,传给HTMLHint.verify(html, config) - Astro:用
onPreBuild钩子读取astro.build.renderedHtml,比扫./dist快 3 倍以上 - Hugo:没法直接 hook 渲染结果,只能退一步,在构建后立即运行
npx htmlhint --config .htmlhintrc ./dist/**/*.html,但必须确保.htmlhintrc放在./dist目录下,否则 fallback 到根目录宽松配置
规则配置必须按 SSG 引擎特性分组
一套 .htmlhintrc 打天下?会误报炸锅。Eleventy 默认注入 JS 到 <head>,Astro 允许无值属性如 client:load,Hugo 模板变量可能残留未转义字符——这些都不是 bug,是引擎行为,规则得跟着调。
典型配置差异:
立即学习“前端免费学习笔记(深入)”;
- Hugo:关掉
doctype-first(front matter 可能出现在 DOCTYPE 前),开attr-no-unsafe-char防{{ .Title }}渲染后带恶意字符 - Eleventy:开
id-unique和head-script-error,它默认把 JS 注入<head>,容易引发执行顺序问题 - Astro:必须禁用
attr-value-not-empty,否则<MyButton client:load>直接被标为错误
别把 Prettier 当 HTML 质量守门员
prettier 格式化再漂亮,也救不了语义缺陷。它能把 <div><p>hello</p></div> 缩进对齐,但不会告诉你 <div> 包 <p> 是合法却冗余;更不会发现 <button onclick="location.href='x.html'"> 这种可访问性灾难。
真实场景里,Markdown 经 remark-html 渲染成 HTML 后,prettier 完全无感,而 htmlhint 能立刻捕获:alt 缺失、aria- 拼错、<h2> 直接跟在 <h4> 后面。
-
attr-validate规则能拦住role="buton"这类低级拼写错误 -
script-max-length和inline-script是防 Hugo unsafe mode 下意外注入<script>的关键 -
attr-max-len比prettier的printWidth实在得多——一行塞 200 个 class 名字依然合法,但attr-max-len可强制截断
CI 与本地 HTMLHint 报错不一致怎么快速排查
最常踩的坑不是规则写错,而是环境漂移:CI 用的 Node 版本、HTMLHint 版本、甚至换行符(\r\n vs \n)都可能导致解析差异。缓存的 node_modules 更是隐形炸弹。
实操建议:
- CI 脚本开头加
rm -rf node_modules && npm ci,杜绝缓存污染 - 在
package.json中锁死htmlhint版本,比如"htmlhint": "7.3.4",别用^或~ - 本地和 CI 都用
--format=unix输出,确保行号列号对齐,GitLab CI 才能高亮准确定位 - 检查
.htmlhintrc是否被其他工具(如prettier-plugin-html)忽略——需显式设htmlhint: { globals: { "htmlhint": true } }
真正难缠的,是那些模板变量渲染后才暴露的结构断裂:比如 JSON 数据直插 data-foo 导致引号截断、<script> 里嵌了未转义双引号。这类问题 HTMLHint 捕不到,得靠构建后用 cheerio 或 axe-core 补漏。



















