htmlhint是唯一能嵌入构建流程并提前拦截跨平台html问题的静态检查工具,需显式启用attr-no-unsafe-char、attr-value-not-empty、head-script-disabled、id-unique等关键规则。

HTMLHint 配置必须覆盖跨平台基础兼容性
跨平台打包(如 React Native + Metro、Electron、Tauri 或鸿蒙 OpenHarmony)对 HTML 片段的容忍度远低于浏览器环境——尤其是模板内联脚本、非标准属性、未闭合标签,在 WebView 或原生渲染器中可能直接导致白屏或解析中断。HTMLHint 是唯一能嵌入构建流程并提前拦截这类问题的静态检查工具。
关键配置项需显式启用:
-
"attr-no-unsafe-char": "error":防止onclick="javascript:..."类注入式写法在鸿蒙 WebView 中被拦截 -
"attr-value-not-empty": "error":避免<img src="">在 Electron 渲染进程里触发 404 并阻塞资源加载 -
"head-script-disabled": "error":禁止<script></script>出现在,Metro 打包时会跳过该 script,但鸿蒙webview可能执行失败 -
"id-unique": "error":多个平台 WebView 共享 DOM 作用域,重复 ID 会导致document.getElementById返回不可预期节点
W3C 验证器只适用于最终 HTML 输出,不适用构建中间态
很多团队误把 W3C Markup Validation Service 当作 CI 检查入口,结果在打包后才发现 <template></template> 标签嵌套错误或自定义元素未声明。问题在于:W3C 验证器只能校验完整、已展开、无条件编译的 HTML 文件,而跨平台打包流程中常见的 html-webpack-plugin 模板、Vue SFC 的 <template></template>、React JSX 中的 HTML 片段,都属于“未求值中间态”。
正确做法是分层验证:
- 源码层:用
eslint-plugin-html+eslint-plugin-vue(Vue)或eslint-plugin-react(React)检查 JSX/模板语法 - 构建产物层:在
html-webpack-plugin的afterEmit钩子中提取生成的index.html,调用w3c-validateCLI 进行一次最终校验 - 鸿蒙/OpenHarmony 场景:额外校验
config.json5中声明的mainPath对应 HTML 是否通过 W3C 验证,否则AbilityStage初始化失败
StyleLint 和 ESLint 无法替代 HTML 结构检查
有人试图用 stylelint 检查 style 属性、用 eslint 检查内联 on* 事件,但这只是碎片化防御。HTML 的结构性缺陷(比如 <div>
<p></p>
<div></div> 这种非法嵌套)既不会触发 ESLint 规则,也不会被 StyleLint 捕获,却会在 Android WebView 中触发 DOM 解析异常,且错误堆栈不指向源码位置,只显示 <code>Failed to execute 'insertBefore' on 'Node'。
真正有效的组合是:
- HTMLHint 负责标签合法性、嵌套规则、DOCTYPE 声明
- axe-core(CLI 模式)负责可访问性语义层级,例如
<h1></h1>缺失或<nav></nav>内无链接 - 自定义脚本扫描
data-*属性是否全部被 JS 实际消费(避免跨平台时因原生桥接未注册导致静默失效)
CI 流程中 HTML 质量检查必须早于资源打包
在 Webpack 或 Metro 构建流水线里,如果把 HTML 质量检查放在 webpack --mode=production 之后,就失去了修复窗口——此时 index.html 已被注入 hash 资源路径、压缩、甚至 base64 内联,HTMLHint 无法定位原始模板行号,报错信息变成 Line 1, Column 1287: Tag <div> is not closed,根本没法回溯到 Vue 单文件组件里的哪一行。<p>推荐插入点:</p>
<ul>
<li>Webpack:在 <code>HtmlWebpackPlugin 的 beforeEmit 钩子中获取 compilation.assets[htmlFile].source(),传给 HTMLHint API 校验
config.transformer.getTransformOptions 注入预处理函数,对所有 .html 或 .htm 入口做同步校验build-profile.json5 的 customizeBuild 阶段调用 Node.js 脚本,读取 src/main/resources/base/profile 下 HTML 文件最易被忽略的是:HTMLHint 默认不校验自定义元素(如 <my-button></my-button>),但在跨平台环境里,这些标签若未被对应原生模块注册,就会退化为空节点——必须配合 "tag-name-lowercase": "error" 和自定义 "tag-allowed" 白名单规则使用。











