一个 favicon 只是一张 16×16 像素的小图,平常没人会注意。一旦它坏了,它就成了唯一被注意到的东西——标签页里那张撕破的纸片、iPhone 主屏上页面的截图、一个 "添加到主屏幕" 之后什么都没安装的提示。
Favicon 审计是我们对任意站点跑的最快、最小的一次发布前检查。本指南是它的操作手册:审计到底查什么、有意略过什么、以及如何把它嵌进发布流程而不变成一种仪式性负担。
审计具体查什么
审计通过我们加固过的 CORS 代理抓取 URL,解析 HTML,找出决定浏览器、搜索爬虫、主屏安装器能否各自拿到正确图标的六项声明:
/favicon.ico——所有浏览器在没有其他声明时的兜底路径- Apple 触屏图标——
<link rel="apple-touch-icon">或/apple-icon.png - 通用图标——
<link rel="icon">,尺寸 ≥ 32×32 - Web 应用清单——
<link rel="manifest">已引用且可达 - 主题色——
<meta name="theme-color">已设置 - 视口元数据——
<meta name="viewport">已设置
结果表中的每一行只有三种状态:通过、缺失、检查。没有评分系统,也没有加权规则。清单就是清单,目的是把它当成一份 checklist,而不是一份成绩单。
审计有意不查什么
一些看起来像 favicon 工作、但其实属于别处的事:
- 图片质量——图标是否设计良好、在 16×16 下是否清晰、是否符合品牌调性。这是设计判断,不是检查。
- CDN 可达性——代理可以确认 link 标签存在,但图标本身只用标准
fetch加图片 MIME 嗅探来请求。如果你的 CDN 有地理屏蔽,审计会显示 link 标签通过,但某些地区的真实用户根本加载不到文件。 - 跨浏览器渲染——我们用 Chromium 跑测试。Safari 的 iOS 特有行为(圆角、玻璃高光)和 Firefox 隐私窗口的图标缓存不在覆盖范围内。
- manifest 自身的合法性——我们只检查 manifest 是否被引用,不检查内部 JSON 是否格式正确、是否包含所有必填字段。manifest 校验请用单独的 manifest 验证器。
检查通过 = link 标签存在且可达。检查失败 = link 标签缺失或 URL 返回了非图片响应。整套契约就是这些。
什么时候跑
按"抓到真实 bug 的频率"排序,三个时机:
- 发布前,对生产 URL 跑,最后一次内容模板锁定之后。favicon 回归几乎都来自模板变更,而不是图标资源本身。
- 任何模板大改之后——CMS 升级、设计系统迁移、字体替换、任何会触及
<head>渲染的改动。 - 排查具体投诉时——合作方说"你们站点的标签页图标坏了"、设计师发现 iOS 主屏不对、销售工程师发现 PWA 安装提示带的不是正确的品牌。
不要在 CI 里每次提交都跑。代理会发一次网络请求,审计不是用来抓代码评审里就能看到的回归的。把它留给上述几个时机。
如何读懂输出
结果表有三列:检查项、要找的路径或选择器、状态。看这张表的时候请记住几件事:
/favicon.ico通过很关键,哪怕你已经声明了<link rel="icon">。 一些爬虫和老浏览器的标签页恢复流程只会请求/favicon.ico。跳过它不会给你省下什么,只会让你的服务器日志里多一条 404。- 如果你不发 PWA,manifest 链接的"检查"状态完全可以接受。 manifest 是可安装 PWA 的必要条件。没有 PWA 的站点,缺这个链接是信息性的,不是失败。
- **
theme-color的"缺失"单看通常不紧急,**但它会改变 Chrome 在 Android 上绘制地址栏的方式,而那是大多数用户唯一会注意到的视觉差异。如果你有品牌色,就声明它。
审计是"浅"检查,这不是 bug,是设计。它不会抓出所有问题,也不会告诉你问题为什么发生。它的工作就是告诉你上述六项声明里"有没有"问题,而不是替你修。
常见失败与修复
按出现频率排序的几个常见失败:
1. 重设计时 CMS 模板把 <link rel="apple-touch-icon"> 这行去掉了。 这在视觉大改后表现为触屏图标的"缺失"。修法:往公共资源里加一张 180×180 的 PNG,并在 head 里加 <link rel="apple-touch-icon" href="/apple-icon.png">。正确位置是 CMS 的 head 模板——不是页面模板。
2. favicon 托管在已经停用的第三方域名上。 这表现为 /favicon.ico 的"缺失",即便 link 标签还在。修法:把 favicon 放到和页面同源。浏览器不在乎 URL,但爬虫和老代码在乎。
3. manifest 被引用,但文件本身 404。 这表现为"检查"状态,因为 link 标签有效但 fetch 失败。修法:确认 manifest 路径指向真实存在的文件。审计能标记 link,但 manifest 验证器会告诉你内容错了。
4. 主题色在 CSS 里设了,但 meta 标签没设。 主题色只从 meta 标签读取,不读 CSS 变量。审计会正确地标记为缺失。修法:在 head 加 <meta name="theme-color" content="#hex">。
嵌入发布流程
最干净的使用方式:把它和一次页面速度检查、一份内容快照 diff 并列为发布前最后三步之一。简单流程:
- 在预发 URL 上跑一次审计。
- 确认六行全绿。
- 如果有红或黄,要么发布前修,要么在 launch doc 里显式记录。
- 上线落地后,在生产 URL 上再跑一次。
- 把结果存到 launch 频道里。
整个流程就这些。审计不是 CI 闸门、不是监控检查、也不是周期性扫描。它是发布那一刻对六项声明是否就位的单次确认。
什么时候该升级到自建系统
如果你一周跑这个审计超过几次,就到了一个自建系统更划算的临界点。几个信号:
- 你在发 PWA,需要审计校验 manifest 内容本身,而不仅仅是它存在与否。
- 你有多套环境(preview、staging、prod),需要审计对它们并发跑并出 diff 报告。
- 你需要审计登录后才能看到的页面,而 CORS 代理模型做不到。
- 你有需要自动执行的品牌规范——错误的图标尺寸、错误的文件格式、manifest 主题色不对。
上述任何一种情况下,对的解法是一套对接你部署流水线的自定义工具,带着你的品牌和产品需要的规则跑。免费审计是个合适的起点,不是终局。
审计地址:/tools/favicon-audit。每次发布前在预发 URL 上跑一次。代理每次审计只发一次 fetch;除了你提交的 URL,没有任何数据被存储或发给第三方。