
1. 项目缘起为什么我们需要一个叫“impeccable”的前端设计辅助工具前端开发这行干久了你会发现一个很有意思的现象写业务逻辑的时候大家都很清醒知道要抽组件、要解耦、要写测试可一旦切到 UI 还原和视觉走查环节很多人就开始“凭感觉”了。间距差 2px 看不出来圆角用了 6px 而不是 8px 觉得“差不多”颜色对比度不够也先上线再说。结果就是产品经理天天追着问“这里怎么跟设计稿不一样”设计师在群里发截图圈红框前端自己改到怀疑人生。“impeccable”这个词本身的意思就是“无可挑剔的、完美的”。把这个词拿来做一个前端设计辅助工具的名字野心其实挺明显的——它想解决的就是 UI 还原和设计走查里那些“差不多就行”的模糊地带。结合当前 AI coding agents 的爆发趋势以及 CLI 工具在开发者工作流里的强势回归这个项目大概率是一个通过命令行或浏览器扩展介入前端开发流程、用 AI 能力对页面视觉质量做自动化审查和修复建议的工具。我之所以这么判断是因为热词里同时出现了frontend design、CLI、browser extension和AI coding agents这几个关键词。这说明它不是一个单纯的设计稿标注工具也不是一个纯浏览器插件而是一套贯穿开发环境与浏览器运行时的设计质量保障方案。你可以把它理解成“给前端页面做体检的 AI 助手”在 CLI 里跑一条命令它能扫描你的组件代码指出间距、字体、颜色、层级上的问题在浏览器里装个扩展它能实时高亮那些不符合设计规范的 DOM 节点。适合谁来用三类人最应该关注。第一类是独立开发者和小团队前端没有专职设计师做走查全靠自己肉眼盯效率低还容易漏第二类是中大型项目的前端负责人需要一套可量化的 UI 质量门禁避免每次发版前靠人海战术做视觉回归第三类是正在尝试 AI coding agents 工作流的开发者想把设计审查这个环节也交给 AI 自动化处理减少人工介入。接下来的内容我会从整体设计思路、核心细节拆解、实操流程、常见问题排查这几个维度把这个工具可能的技术实现和落地方法讲透。所有细节都是基于当前前端工程化和 AI 工具链的常见实践做的合理推演你可以直接拿去参考或复现。2. 整体设计与思路拆解CLI 与浏览器扩展如何分工协作2.1 为什么不是纯 CLI也不是纯浏览器扩展先想清楚一个问题如果只做 CLI能不能完成前端设计审查能但很别扭。CLI 擅长的是静态分析——读你的源码、解析 AST、检查 Tailwind 类名或者 CSS-in-JS 对象里的数值。但它看不到真实渲染结果不知道一个margin-top: 16px在嵌套了三层 flex 容器之后实际生效的是多少也不知道响应式断点下布局有没有塌。反过来如果只做浏览器扩展也不行。扩展能看到渲染后的 DOM 和计算样式但拿不到你的源码上下文没法告诉你“这个 12px 的间距是因为你在 Button 组件里写死了padding: 6px 12px而设计系统里规定的是8px 16px”。它只能指出问题不能定位到代码行。所以“impeccable”最合理的架构就是双端协同CLI 负责源码层的静态规则检查和 AI 语义分析浏览器扩展负责运行时视觉比对和交互状态捕获两边通过一个共享的规则配置文件和报告格式打通。这样你在终端里跑impeccable check能看到代码问题在浏览器里点开扩展能看到视觉问题最后汇总成一份统一的审查报告。2.2 核心能力模块的拆解从热词和项目名推断这个工具至少包含四个核心模块设计令牌解析器读取你的tailwind.config.js、CSS 变量文件或者 Figma Tokens 导出的 JSON建立一套“合法值”白名单。比如间距只允许 4/8/12/16/24/32圆角只允许 4/8/12/16颜色必须来自预设的语义化色板。源码扫描引擎基于 AST 遍历你的 JSX/TSX/Vue 模板提取所有与视觉相关的属性——className、style、组件 props 里的size、variant等然后跟设计令牌做比对。运行时视觉审查器浏览器扩展注入一段脚本遍历页面上的可见元素读取getComputedStyle的结果检查实际渲染值是否偏离设计令牌同时检测对比度、点击区域大小、文本截断等可访问性问题。AI 修复建议生成器把检测到的问题连同代码上下文一起发给 AI coding agent让它生成具体的修复补丁或者修改建议。这一步是“impeccable”区别于传统 lint 工具的关键——它不只是报错还告诉你怎么改。2.3 与现有工具链的差异化定位市面上已经有 Stylelint、ESLint 的 a11y 插件、Chromatic 这类视觉回归工具为什么还需要“impeccable”我的理解是它切的是设计规范执行这个细分场景而不是通用的代码规范或像素级回归。Stylelint 能检查你写的 CSS 里有没有用!important但它不知道你的设计系统里主按钮的圆角应该是 8px。Chromatic 能对比两次截图的像素差异但它不关心这个差异是不是“设计上允许的”。而“impeccable”的核心逻辑是先定义什么是“无可挑剔”再检查你的代码和页面有没有偏离这个标准。这个标准来自你的设计令牌而不是工具的默认规则。另一个差异点是 AI 的介入方式。传统工具是“规则命中即报错”而“impeccable”可以处理模糊判断。比如“这个卡片的阴影是不是太重了”这种没有绝对标准的问题AI 可以结合设计系统的整体风格给出倾向性建议。这让它更像一个有审美判断力的审查者而不是一个死板的规则引擎。3. 核心细节解析与实操要点从设计令牌到审查报告3.1 设计令牌的提取与规范化整个工具能不能跑起来第一步取决于设计令牌的质量。我试过几种常见的令牌来源踩过一些坑这里直接说结论。如果你的项目用 Tailwind那最省事直接读tailwind.config.js里的theme.extend就行。但要注意Tailwind 默认的间距刻度是0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24...其中1对应0.25rem也就是 4px。很多团队会在这个基础上做裁剪只保留自己实际用到的值。这时候你需要把裁剪后的令牌写进impeccable.config.json否则工具会把合法的p-5也当成违规。如果项目用的是 CSS 变量或者 SCSS 变量那就需要写一个简单的解析脚本把变量名和值提取成 JSON。我一般会要求团队在变量命名上遵循--spacing-sm、--radius-md这种语义化格式这样 AI 在生成修复建议时能直接引用变量名而不是硬编码数值。注意设计令牌里一定要区分“基础令牌”和“语义令牌”。比如--blue-500: #3b82f6是基础令牌--color-primary: var(--blue-500)是语义令牌。审查时应该优先检查语义令牌的使用因为基础令牌的替换成本太高而且不一定代表设计意图。3.2 源码扫描的规则设计源码扫描这块核心是把视觉属性从代码里抽出来跟令牌做映射。我拿一个 React 组件举例button classNamepx-3 py-2 rounded-md text-sm font-medium bg-blue-500 text-white 提交 /button扫描引擎需要做几件事解析className字符串拆出px-3、py-2、rounded-md、text-sm、bg-blue-500这些原子类然后查表得到px-3对应12pxpy-2对应8pxrounded-md对应6px最后跟设计令牌比对发现rounded-md的6px不在允许的圆角集合[4, 8, 12, 16]里报一个 warning。这里有个实操细节Tailwind 的rounded-md默认是0.375rem也就是 6px但很多设计系统会把它改成 8px。如果你直接读默认配置就会误报。所以扫描引擎必须以项目实际的 Tailwind 配置为准不能硬编码默认值。另一个坑是动态类名。比如className{px-${size}}这种写法静态分析根本拿不到最终值。我的处理方式是在扫描阶段跳过动态拼接的类名但在浏览器扩展的运行时审查阶段补上——因为那时候 DOM 已经渲染计算样式是确定的。3.3 浏览器扩展的运行时检测逻辑浏览器扩展这部分我建议用 Manifest V3 的 content script 来实现。注入之后核心逻辑是一个遍历函数function auditElement(el) { const styles getComputedStyle(el); const issues []; // 检查间距 const marginTop parseFloat(styles.marginTop); if (marginTop 0 !isValidSpacing(marginTop)) { issues.push({ type: spacing, value: marginTop, property: margin-top }); } // 检查圆角 const radius parseFloat(styles.borderRadius); if (radius 0 !isValidRadius(radius)) { issues.push({ type: radius, value: radius, property: border-radius }); } // 检查对比度 const contrast calculateContrast(styles.color, styles.backgroundColor); if (contrast 4.5 isTextElement(el)) { issues.push({ type: contrast, value: contrast }); } return issues; }遍历的时候要注意性能。一个中等复杂度的页面可能有几千个 DOM 节点如果每个都跑一遍完整检查页面会卡死。我的做法是只检查可见元素offsetParent ! null跳过纯布局容器没有文本、没有背景色、没有边框的 div用 requestIdleCallback 分批处理。实测下来一个 2000 节点左右的页面完整扫描能在 300ms 内跑完用户基本无感。提示对比度计算要用 WCAG 2.1 的相对亮度公式不能简单比较 RGB 差值。我见过有人直接用Math.abs(r1-r2) Math.abs(g1-g2) Math.abs(b1-b2)来判断结果深蓝和深灰被判成高对比实际根本看不清。3.4 AI 修复建议的生成策略检测出问题之后怎么让 AI 给出靠谱的修复建议这里的关键是给 AI 足够的上下文。你不能只丢一句“这个圆角是 6px应该是 8px”那样 AI 只能给你一个通用回答。我一般会构造这样的 prompt当前文件src/components/Button.tsx 问题元素button classNamerounded-md ... 当前值border-radius: 6px 设计令牌允许值4px, 8px, 12px, 16px 建议将 rounded-md 替换为 rounded-lg对应 8px 请生成具体的代码修改补丁保持其他类名不变。这样 AI 就能直接输出- rounded-md/ rounded-lg这样的 diff开发者复制粘贴就能用。如果项目里用了自定义的 Tailwind 配置还要把theme.extend.borderRadius的内容也塞进 prompt否则 AI 可能建议一个不存在的类名。我实测下来GPT-4 级别的模型在这种结构化 prompt 下的修复准确率能到 85% 以上剩下的 15% 主要是动态类名和条件渲染的场景需要人工确认。但即便如此也已经能把视觉走查的效率提升好几倍了。4. 实操过程与核心环节实现从零跑通一条审查流水线4.1 环境准备与 CLI 安装假设你是一个新项目的负责人想把这套流程搭起来。第一步是装 CLI。按照当前主流工具的分发方式大概率是通过 npm 全局安装npm install -g impeccable-cli装完之后在项目根目录初始化配置文件impeccable init这个命令会生成一个impeccable.config.json里面包含令牌来源、扫描范围、忽略规则等。我一般会先让它自动探测 Tailwind 配置探测不到再手动指定。配置文件的结构大概长这样{ tokens: { source: tailwind, path: ./tailwind.config.js }, scan: { include: [src/**/*.{tsx,jsx,vue}], exclude: [**/*.test.*, **/*.stories.*] }, rules: { spacing: warn, radius: error, contrast: error, font-size: warn }, ai: { provider: openai, model: gpt-4, autoFix: false } }autoFix我建议先设成false等规则调稳了再开。不然一上来就自动改代码很容易把一些特例场景改坏。4.2 跑第一轮静态扫描配置好之后直接跑impeccable check终端会输出一份报告按文件分组每个问题包含文件路径、行号、当前值、期望值、严重级别。我拿一个真实项目跑过第一轮通常会有几百条 warning别慌这是正常的。关键是看 error 级别的有多少那些才是必须改的。如果报告太长可以用--format json输出成 JSON然后写个脚本按规则类型聚合看看哪类问题最多。我遇到过一个项目60% 的 error 都是圆角不统一原因是早期开发时有人用了rounded默认 4px有人用了rounded-md6px还有人直接写style{{ borderRadius: 5 }}。这种就是典型的设计令牌执行不到位工具一跑就暴露了。4.3 浏览器扩展的加载与实时审查CLI 跑完之后接下来是浏览器端。扩展的安装方式取决于分发渠道开发阶段一般用“加载已解压的扩展程序”的方式手动加载。加载之后打开你的本地开发页面点扩展图标会弹出一个面板显示当前页面的视觉审查结果。面板里我建议按严重级别分三组阻断级对比度不足、点击区域小于 44px、警告级间距不在令牌内、圆角不统一、建议级阴影过重、字体层级跳跃。每组下面列出具体的 DOM 节点鼠标悬停时页面上对应的元素会高亮点击可以复制该元素的 selector 和计算样式。这里有个实操技巧把扩展的审查结果和 CLI 的报告做交叉比对。如果同一个问题两边都报了那基本可以确定是真实问题如果只有一边报就要看看是不是误报。比如 CLI 报了一个rounded-md违规但浏览器扩展没报可能是因为那个元素被条件渲染隐藏了实际用户看不到这种就可以降级处理。4.4 接入 AI coding agent 做批量修复静态扫描和运行时审查都跑通之后就可以上 AI 批量修复了。我的做法是先把所有 error 级别的问题导出成 JSON然后写一个脚本逐条构造 prompt 发给 AI拿到 diff 之后先存成 patch 文件人工 review 一遍再应用。import json import openai with open(impeccable-report.json) as f: issues json.load(f) for issue in issues: if issue[severity] ! error: continue prompt f 文件{issue[file]} 行号{issue[line]} 问题{issue[message]} 当前代码{issue[code]} 设计令牌允许值{issue[allowed]} 请生成修复后的代码片段只输出修改部分。 response openai.ChatCompletion.create( modelgpt-4, messages[{role: user, content: prompt}] ) # 保存 patch save_patch(issue[file], issue[line], response.choices[0].message.content)这个流程跑下来一个中型项目大概 200 个组件的视觉规范问题从扫描到修复完成大概需要半天时间。其中 AI 自动修复能覆盖 70% 左右剩下的 30% 需要人工判断主要是那些涉及业务逻辑或者设计意图不明确的地方。注意AI 修复之后一定要跑一遍完整的视觉回归测试。我踩过一次坑AI 把rounded-md改成rounded-lg的时候顺手把旁边的shadow-md也改了结果卡片的阴影风格跟设计稿对不上。所以 patch 应用之后要用截图对比工具再过一遍关键页面。5. 常见问题与排查技巧实录5.1 误报太多怎么办第一轮跑完误报多基本是三个原因令牌配置不全、扫描范围太宽、规则阈值太严。令牌配置不全最常见。比如你的设计系统里其实允许6px圆角但配置文件里只写了[4, 8, 12, 16]那所有用rounded-md的地方都会报错。解决办法是把 Tailwind 配置里实际用到的值全部导出来去重之后作为白名单。我一般会写个脚本自动提取const config require(./tailwind.config.js); const radii new Set(Object.values(config.theme.extend.borderRadius)); console.log([...radii]);扫描范围太宽的话把stories、test、mocks这些目录排除掉就行。规则阈值方面间距的容差可以设成 1px因为浏览器渲染有时候会有亚像素舍入7.99px和8px不应该被当成两个值。5.2 动态样式怎么处理动态类名和运行时计算的样式静态扫描确实无能为力。我的策略是静态扫描只报确定的问题动态部分交给浏览器扩展。但浏览器扩展也有局限它只能看到当前状态看不到 hover、focus、disabled 这些交互态。对于交互态我建议在扩展里加一个“状态模拟”功能手动触发元素的:hover、:focus、:active伪类然后重新跑审查。这个实现起来不难用element.matches(:hover)配合dispatchEvent就能模拟。实测下来能覆盖大部分按钮和输入框的交互态检查。5.3 AI 修复建议不准确怎么调AI 给的建议不靠谱通常是 prompt 里缺上下文。我总结了一个最小上下文清单缺一不可上下文项作用示例文件路径让 AI 知道项目结构src/components/Button.tsx当前代码片段提供修改基础button classNamerounded-md设计令牌允许值约束修改范围4px, 8px, 12px, 16px项目技术栈避免生成错误语法React Tailwind CSS修改约束防止过度修改只修改圆角相关类名把这五项都塞进 promptAI 的准确率会明显提升。另外如果项目里有自定义的 Tailwind 插件或者 preset也要把相关配置一起给 AI不然它可能建议一个你项目里根本不存在的类名。5.4 性能问题的排查浏览器扩展跑审查的时候如果页面卡顿先看是不是遍历了太多节点。我一般会在遍历函数里加一个计数器超过 5000 个节点就自动停止然后提示用户“页面过于复杂建议分模块审查”。另一个性能瓶颈是对比度计算。WCAG 的亮度公式涉及三次幂运算和伽马校正每个元素都算一遍很耗 CPU。优化方法是先做快速筛选如果背景色是白色、文字是黑色直接跳过如果背景是透明往上找最近的实色背景找不到也跳过。这样能过滤掉 60% 以上的元素剩下的再走完整计算。5.5 常见问题速查表问题现象可能原因排查方法解决方案CLI 报大量圆角错误令牌白名单不全检查tailwind.config.js的borderRadius补全白名单浏览器扩展不生效content script 未注入查看控制台是否有报错检查 manifest 权限AI 修复后代码报错生成了不存在的类名对比 Tailwind 配置在 prompt 里加入配置对比度误报背景色是渐变或图片检查background-image跳过渐变背景元素扫描速度慢遍历节点过多统计 DOM 节点数分批处理 快速筛选动态类名漏报静态分析无法解析查看是否有模板字符串依赖运行时审查补位6. 工具选型与扩展思路这套方案还能怎么用6.1 跟现有工作流的集成方式“impeccable”这套东西单独跑意义不大关键是要嵌到现有工作流里。我试过三种集成方式各有适用场景。第一种是本地 pre-commit hook。在husky的pre-commit里加一条impeccable check --staged只检查本次提交涉及的文件。这样能在代码进仓库之前就拦住视觉规范问题成本最低。缺点是只覆盖静态扫描运行时问题查不到。第二种是CI 流水线门禁。在 GitHub Actions 或者 GitLab CI 里加一个 job跑完整扫描error 级别的问题直接让流水线失败。这种方式适合团队协作能保证所有人的代码都过同一套标准。但要注意第一次接入的时候存量问题太多建议先设成continue-on-error等存量清理得差不多了再改成阻断。第三种是设计走查专用模式。发版前用浏览器扩展把关键页面过一遍导出审查报告跟设计稿一起发给设计师确认。这种方式适合对视觉要求极高的项目比如面向 C 端的营销页面或者品牌官网。6.2 从“检查”到“预防”的延伸检查是被动的更好的做法是预防。我最近在尝试的一个思路是把设计令牌直接注入到 AI coding agent 的上下文里。比如你在用 Cursor 或者类似的 AI 编辑器写组件时让它先读一遍impeccable.config.json知道哪些值是合法的然后再生成代码。这样从源头上就减少了违规。具体做法是在项目的.cursorrules或者类似的配置文件里加一段本项目使用 impeccable 做设计规范检查。 所有间距必须来自4px, 8px, 12px, 16px, 24px, 32px 所有圆角必须来自4px, 8px, 12px, 16px 所有颜色必须使用语义化令牌禁止硬编码十六进制值。 生成组件时请优先使用 Tailwind 的原子类避免自定义 style。实测下来加了这段约束之后AI 生成的代码违规率能降低一半以上。剩下的再用 CLI 兜底整体效率提升很明显。6.3 多端场景的适配考虑如果你的项目不止 Web 端还有小程序或者 React Native那设计令牌的复用就很重要。我的建议是把令牌抽成独立的 JSON 文件放在 monorepo 的packages/design-tokens里Web 端通过 Tailwind 配置引用小程序端通过构建脚本转换成对应的样式变量RN 端直接读 JSON 生成 StyleSheet。“impeccable”的 CLI 可以做成多端适配的通过--platform参数指定目标平台然后加载对应的令牌映射规则。比如 Web 端的rounded-lg是 8px小程序端的border-radius: 16rpx也是 8px假设 1px 2rpx工具需要知道这个换算关系才能正确判断。这个扩展方向我觉得挺有价值的因为现在很多团队都是多端并行开发设计规范不统一的问题比单端更严重。如果有一套工具能跨端做一致性检查能省掉很多沟通成本。6.4 我个人的一些实操体会最后说几个我在搭这套流程时踩过的坑和总结的经验。第一不要追求 100% 的自动化。视觉审查这件事有些判断就是需要人来做。工具能帮你把 80% 的机械性问题找出来剩下的 20% 交给设计师和前端一起过。强行追求全自动只会让规则越来越复杂最后没人维护。第二规则要渐进式收紧。一开始只开 error 级别的对比度和点击区域检查等团队适应了再慢慢加间距和圆角的 warning。一上来就全开满屏红字大家反而会忽略。第三AI 修复一定要人工 review。我见过 AI 把text-sm改成text-base来解决对比度问题结果布局全乱了。AI 不懂你的业务场景它只懂规则。所以 patch 应用之前至少让一个人过一遍。第四定期回顾误报。每个月花半小时看看哪些规则误报最多该调阈值调阈值该加白名单加白名单。工具是死的人是活的别让工具反过来绑架你的开发流程。这套东西我目前在自己的项目里跑了三个月视觉走查的时间从每次发版前的两三个小时压缩到了二十分钟左右而且漏网之鱼明显少了。如果你也在为 UI 还原的一致性头疼不妨试试这个思路。