很多前端同学在把 PWA 安装到 Android 手机桌面后,都会发现 Logo 变得模糊或者被拉伸。这通常是因为 web app manifest 里的 192 和 512 尺寸图标配置出了问题。Android 系统不会去猜你要用哪张图,它只会严格解析 manifest.json 文件,然后找尺寸最接近的那张。如果尺寸不对或者内边距没留对,最后出来的效果就是惨不忍睹。
跑一下 Google 的 Lighthouse 审计,如果你的 manifest 里找不到 192x192 和 512x512 的 PNG 图标,PWA 这项直接挂掉。这俩不是随便定的数字。192px 是桌面快捷图标的标准尺寸,而 512px 是 Android 用来生成启动页(splash screen)的素材。缺一不可,而且必须完美。
这篇文章不展开讲 PWA 的全套生态——需要补基础的同学可以看我们的 Web App Manifest Favicon 指南。我们这里只死磕 192 和 512 像素这两个图标:为什么老是配置失败、怎么正确生成、以及能直接跑通的 JSON 代码。
前提:搞定你的源文件
在开始调整尺寸之前,你得先准备一张高质量的源文件。千万别拿一张 16x16 的 favicon 去强行放大。你需要一张矢量 SVG 源文件,或者至少 1024x1024 像素的 PNG。
如果你手里只有位图,放大到 512px 肯定会糊。这就是为什么现在行业标准都直接用 SVG。无限缩放,清晰度不掉一像素。如果你的 Logo 上面有一堆细小的文字,那在缩放时绝对会翻车——建议看看我们的 Favicon 设计避坑指南,了解一下为什么在小尺寸下做减法才是正解。
实操:生成与配置 Icons
下面直接上代码和操作。你可以用任何图像编辑软件,但我们这里用标准 CLI 工具和原生 JSON 配置,方便你直接塞到自动化构建流水线里。
Step 1: 导出 192 和 512 的 PNG
用你顺手的编辑器(Figma、Sketch 或 Adobe XD)打开源 SVG 文件,导出两张独立的 PNG。命名必须精确为 icon-192.png 和 icon-512.png。规范的命名不仅让 manifest 更易读,后期排查问题也方便。
如果你用的是 Vite 或者 Webpack 这类构建工具,可以配个插件自动搞定。如果是普通的静态站点,直接把图扔进 /public/icons/ 目录就能用。
Step 2: 编写 Manifest JSON
打开你的 manifest.json 文件。你需要在 icons 数组里显式声明这两个图标。下面是你可以直接复制粘贴的配置:
{
"name": "My Awesome App",
"short_name": "Awesome",
"icons": [
{
"src": "/icons/icon-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/icons/icon-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
}
]
}注意 purpose 字段。设为 any 就是告诉浏览器这张图可以在任何场景下使用。后面讲踩坑点的时候会提到 maskable icons,那是大部分开发者翻车的地方。
Step 3: 在 HTML 中引入 Manifest
如果浏览器不知道 manifest 的存在,写了也没用。在你的 HTML 文档的 <head> 里加上这一行:
<link rel='manifest' href='/manifest.json'>搞定了。部署上线后,Android 设备就会读取这个文件,自动拉取正确的 192px 和 512px 图标。
配置 192 和 512 图标的常见坑
JSON 写对只算成功了一半。很多同学 Lighthouse PWA 审计跑不过,往往是因为一些设计或配置细节没到位。下面是我在 Code Review 时见得最多的三个问题。
坑 1:无视 'purpose' Maskable 陷阱
Android 8+ 引入了自适应图标。如果你想让图标看起来像原生应用一样,能适配各种圆形或圆角矩形桌面,你需要 maskable icon。但是,你不能直接在原有的 192 和 512 PNG 上加个 purpose: "maskable" 就完事了。
Maskable icons 需要满版的背景色,而且你的 Logo 必须放在安全区(画布中心的 80% 区域)内。如果 Logo 紧贴边缘,Android 桌面强行裁剪后就会变得很诡异。你需要单独导出留白版本,然后这样声明:
{
"src": "/icons/maskable-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
}在 manifest 里,你可以声明多个 192x192 的条目,只要它们的 purpose 不同就行。强烈建议 192 和 512 尺寸各配一个 any 和一个 maskable。
坑 2:服务器返回了错误的 MIME Type
如果你发现图标在桌面端正常,但在手机上死活加载不出来,查一下服务器的响应头。有些配置严格的服务器会把 PNG 默认以 application/octet-stream 返回,而不是 image/png。
Android Chrome 对 manifest 里的 MIME type 极其敏感。如果你 JSON 里写的 type 跟服务器返回的 Content-Type 对不上,系统会直接静默丢弃这个图标。确保你的 Nginx 或 Apache 正确映射了 .png 文件的响应头。
坑 3:在 512px 画布里塞太多细节
给了你 512x512 的画布,不代表你要把公司使命宣言全塞进去。当 Android 把这个 512px 的图标缩小用做通知栏小图标时,那些细节全会糊成一团。
看看大厂是怎么做的,比如支付宝或者微信的 PWA 图标,都是在纯色背景上放一个高对比度的简单标识。不管是在启动页放大到 512px,还是在通知栏缩小到 48px,看着都很锐利。做减法就对了。
验证你的配置
别写完直接上线就祈祷没事。你需要验证 manifest icons 是否生效。打开 Chrome DevTools,切到 Application 面板,点击 Manifest。你应该能在 'Icons' 区域清晰地看到 192 和 512 的图标。
如果这里显示正常,没有碎图图标,那就稳了。如果你想看看其他网站是怎么处理内边距的,可以用 Mzu favicondl 直接拉取它们的 manifest 文件,对比一下别人的配置。
只要源文件没问题,正确配置 web app manifest icons 192 512 顶多花你十分钟。别瞎猜,按规矩导出尺寸,声明对的 MIME type,你的 PWA 在 Android 上就能拥有原生的质感。