htmlq 不是校验器,仅提取不验证;真正落地的 html 质量校验需分层:构建时用 html-validate 扫静态结构,运行时在 serverless 函数中嵌入三行轻量守卫逻辑,并全部容器化固化。

不能靠 htmlq 做 HTML 质量校验,它只提取不验证;真正能落地的实时校验体系,必须分层:构建时用 html-validate 扫静态结构,运行时在 Serverless 函数里加三行守卫逻辑,且全部容器化固化。
htmlq 不是校验器,别把它当质量门禁用
常见错误现象:在 Lambda 函数里跑 htmlq 'title' 返回空,就认为
-
htmlq 'body'返回空,可能是 HTML 为空、解析失败,也可能是文档根本没标签,它不会告诉你原因 - 用
htmlq '*'全量提取,在 128MB 内存档的 Lambda 里极易触发 OOM,尤其含大量内联 JS 时 - 它无法识别
onerror="alert(1)"或javascript:这类高危模式,也不报告<header></header>在<main></main>外嵌套这类语义错误
Serverless 函数返回前必须插三行轻量守卫
构建时扫描拦不住模板字符串拼接错误,所以必须在函数实际返回 HTML 前做最小可行检查。这些逻辑要极轻(
- 检查
<title></title>是否存在:strings.Contains(htmlBody, "<title>")</title>或正则<title>[^</title>,缺失直接返回 HTTP 500 - 禁止内联样式:
strings.Contains(htmlBody, "style="),发现即拒绝响应——不是为了美观,而是防止绕过 CSP - 确认 charset 声明:
strings.HasPrefix(htmlBody, "<meta charset="utf-8">")或等效<meta http-equiv="Content-Type" content="text/html; charset=utf-8">,否则中文首屏固化乱码
别用 document.querySelector 或 cheerio.load——Serverless 环境没有 DOM,jsdom 启动开销远超 htmlq,且冷启动延迟常突破 100ms 阈值。
CI/CD 流水线里 HTML 校验必须容器化执行
本地跑 html-validate 和流水线结果不一致,根本原因是 Node 版本、规则版本、甚至 libxml2 行为漂移。容器化不是为了“高大上”,而是锁定可重现性。
- 基础镜像用
node:18-alpine,全局安装html-validate@5.2.0(非 devDependencies),避免package-lock.json失效 -
.htmlvalidate.json必须 COPY 进镜像,不挂载——挂载会破坏构建可重现性 -
CMD ["html-validate", "--config", ".htmlvalidate.json", "public/**/*.html"],失败时 exit 1,让 CI 自然中断 - 若用 GitHub Actions,显式
actions/setup-node+npm install html-validate --no-save,路径通配符加引号防 shell 展开
微前端和组件内 HTML 片段得用 eslint-plugin-html 补位
html-validate 和 htmlhint 只认纯 .html 文件,对 Vue 的 <template></template> 或 React 的 dangerouslySetInnerHTML 完全无感——这是高频 XSS 漏洞温床。
- 安装
eslint-plugin-html,在.eslintrc.js中配置processor: "html/eslint-plugin",把 HTML 片段提取给 ESLint 解析 - 它能捕获
v-html="${userInput}"这类危险拼接,但不能查clss="foo"拼写错误——这类还得靠htmlhint的attr-name-style规则 - 微服务多子应用场景下,按目录隔离配置:
app-vue/.eslintrc.js和app-react/.eslintrc.js分别定义 processor,CI 步骤独立运行、独立失败
最易被忽略的是动态插入点:服务端拼的 innerHTML 字符串、模板字面量里的 HTML 片段、甚至 res.send(<div>${content}</div>) ——这些地方没经过任何 lint,却直出到浏览器,是质量盲区中最硬的骨头。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











