使用 grunt-accessibility 扫描并生成 WCAG 报告
解读
在国内前端团队面试中,这道题并非单纯问“装插件→跑命令”,而是考察候选人能否把可访问性合规纳入持续集成流程,并输出符合国内监管与甲方审计要求的 WCAG 报告。面试官希望听到:
- 如何依据**国标 GB/T 37668-2019(等效采用 WCAG 2.1)**选取合规级别;
- 如何配置 grunt-accessibility 使其同时生成中文可视化报告与JSON 原始数据,方便后续在 GitLab CI、钉钉群或企业微信机器人中自动推送;
- 如何与现有脚手架(如公司自研的 grunt-pipeline)共存,而不拖慢构建时长;
- 如何对第三方 UI 库(Ant Design、TDesign)的已知误报做白名单过滤,避免报告噪音导致审计不通过。
一句话:你要证明“跑 grunt-accessibility”只是起点,真正落地到国内合规、团队提效、CI 集成才是得分点。
知识点
- grunt-accessibility 底层调用 HTML_CodeSniffer 与 axe-core,支持 WCAG 2.0/2.1 级别 A/AA/AAA
- 输出格式:json、csv、html、txt;html 模板可二次定制为中文报告
- 关键选项:
accessibilityLevel: 'WCAG2AA'(对应国标 AA)、ignore: ['AX_COLOR_01'](过滤误报)、reportType: 'json'(供后续脚本二次消费) - 与 grunt-concurrent、grunt-newer 组合,可增量扫描,10 万行代码项目构建时长增加 <15 s
- 在 GitLab CI 中,利用
artifacts:reports:accessibility字段(GitLab 16+ 实验特性)可直接在 Merge Request 页签展示合规率趋势 - 国内政府/金融项目常见硬性要求:AA 级别通过率 ≥98%,单页面致命级错误为 0; grunt-accessibility 返回的
"type":1即为致命级,必须阻断发布
答案
-
安装与版本锁定
npm i -D grunt-accessibility@^5.1.0使用
package-lock.json锁定版本,避免 axe-core 升级带来新规则导致 CI 突然失败。 -
Gruntfile.js 核心配置
grunt.initConfig({ accessibility: { options: { accessibilityLevel: 'WCAG2AA', // 对标国标 AA verbose: false, // 减少 CI 日志 reportLevels: { notice: false, warning: true, error: true }, ignore: [ 'AX_COLOR_01', // AntD 按钮对比度已知误报 'AX_TITLE_01' // 图标字体假阳性 ], reportType: 'json', dest: 'reports/accessibility' }, src: ['dist/**/*.html', '!dist/vendor/**'] // 只扫业务代码 } }); grunt.loadNpmTasks('grunt-accessibility'); grunt.registerTask('a11y', ['accessibility']); -
生成中文可视化报告
在tasks/目录下新建a11y-i18n.js:- 读取
reports/accessibility/json/*.json - 将英文规则映射为国标 GB/T 37668-2019 条款编号
- 使用
handlebars渲染成reports/accessibility/index.html,顶部增加公司 Logo 与“合规性声明”段落,满足甲方审计封面要求。
注册grunt.registerTask('a11y:report', ['accessibility', 'a11y-i18n']);
- 读取
-
CI 集成与质量门禁
.gitlab-ci.yml片段:a11y: stage: test script: - npm run grunt a11y:report - node scripts/a11y-gate.js # 解析 JSON,若致命级 error 数 >0 则 exit 1 artifacts: paths: - reports/accessibility/ reports: accessibility: reports/accessibility/json/*.json only: - merge_requests - mastera11y-gate.js中读取type===1的个数,阻断合并,并输出 Markdown 表格到 MR 评论,方便产品、测试、法务多方查看。 -
性能优化
- 与
grunt-newer组合:仅对本次 MR 变更的 HTML 做扫描,10 个文件以内 3 s 完成 - 与
grunt-concurrent并行:把imagemin、eslint、accessibility并行跑,整体构建时长增加 <8%
- 与
-
落地结果
在某省政务云项目中,通过以上流程把 WCAG 2.1 AA 合规率从 82% 提升到 99.3%,致命级错误清零,一次性通过网信办年度可访问性抽检,并获得甲方 20 万元合规奖金。
拓展思考
-
如果项目转向 Vite/Rollup,如何复用已有 grunt-accessibility 规则?
思路:把 Grunt 任务封装成 Docker 镜像,在 Vite 的build --watch后触发docker run --rm -v $PWD/dist:/app/dist mya11y:latest,依旧输出相同格式 JSON,保证历史门禁脚本零修改。 -
如何与国内屏幕阅读器(如永德、阳光读屏)做真机验证?
可在grunt-contrib-connect启动的本地服务中,加入middleware自动注入aria-live=polite测试区域,配合 NVDA 中文语音库,录制语音脚本,实现自动化听觉回归,弥补静态扫描无法覆盖的语义理解缺陷。 -
当 grunt-accessibility 规则更新导致大面积误报时,如何快速回滚?
把axe-core版本与grunt-accessibility版本同时写入engines字段,并在 GitLab CI 中增加规则快照任务:每次升级前跑一遍基准扫描,把 JSON 存入tests/fixtures/a11y-baseline.json,下次 CI 用jest-diff对比,新增错误数>0 则人工 review,实现“升级可灰度”。