# 已安装的 PWA 如何获取清单更新

> Chrome 大约每天检查一次已安装 PWA 的清单文件，并且只有在所有窗口关闭之后，才会应用名称或主题色等大多数更新。

**一句话：** 根据 web.dev 的说明，PWA 安装后，Chrome 会定期重新获取其 Web App
Manifest 并与本地副本比对；一组特定字段的变更会触发更新，而更新落地后实际会应用
哪些字段，桌面版 Chrome 与 Android 版 Chrome 并不相同。

## 支持情况

根据本页 web.dev 自身的说明："我们仍在收集 Chrome 之外其他浏览器的数据"
（"We're still gathering data on browsers other than Chrome."）。以下内容仅描述
桌面版 Chrome 与 Android 版 Chrome 的行为，不涉及其他浏览器或引擎。

## 桌面版 Chrome 的更新方式

当 PWA 被启动，或在浏览器标签页中打开时，Chrome 会判断本地清单上次检查变更的时间。
如果自浏览器上次启动以来尚未检查过，或者在过去 24 小时内未检查过，Chrome 就会请求
清单并与本地副本比对。如果特定属性发生了变化，Chrome 会将新清单加入队列，并在应用
的所有窗口关闭后安装它。安装完成后，新清单中的所有字段都会更新，**`icons` 除外**——
桌面版 Chrome 目前还不支持更新图标。

会触发桌面端更新的属性有：`name`、`short_name`、`display`、`scope`、`shortcuts`、
`start_url`（更改 `start_url` 需要清单中已设置 `id`）、`theme_color` 以及
`file_handlers`。

```json
{
  "id": "/",
  "name": "My App",
  "start_url": "/app/v2/",
  "theme_color": "#0b5fff"
}
```

web.dev 指出，如果你把 `display` 从 `browser` 改为 `standalone`，已有用户的应用不会
突然切换为窗口模式——用户此前已经选择的窗口/标签页设置始终会被遵循。

## Android 版 Chrome 的更新方式

Android 版遵循同样的 24 小时检查周期，但分发方式不同：在一个变更的清单被加入队列
后，Chrome 会等到 PWA 的所有窗口都已关闭、**并且**设备正在充电、**并且**已连接
Wi-Fi，才会向服务器请求更新后的 WebAPK。该 WebAPK 到达后，新清单中的所有字段都会
生效——包括桌面版 Chrome 目前还无法更新的 `icons`。

会触发 Android 端更新的属性有：`name`、`short_name`、`icons`、
`background_color`、`display`、`orientation`、`scope`、`shortcuts`、
`start_url`、`theme_color` 以及 `web_share_target`。如果 Chrome 无法从服务器获取
更新后的清单，检查间隔可能会退避到最长 30 天一次。

## 如何在运行时检测

web.dev 的指南描述了通过两个浏览器内置诊断页面查看清单更新信息的方法。
`display-mode` 媒体特性是一个标准信号，页面可以对它做特性检测，但根据 MDN 的说明，
它报告的是顶层浏览上下文的实际显示模式，而不是清单更新是否已经落地：

```js
if ('matchMedia' in window && window.matchMedia('(display-mode: standalone)').matches) {
  // 顶层浏览上下文的实际显示模式是 standalone。
  // 这不能说明清单是否已被重新检查或更新。
} else {
  // matchMedia 不可用，或实际显示模式不是 standalone。
  // 回退时不要据此推断当前处于浏览器标签页或任何清单更新状态。
}
```

根据 web.dev 的说明，Chrome "每次 PWA 启动时都会检查清单变更，即便它是在浏览器
标签页中打开的"（"whenever a PWA is launched, even if it's opened in a browser
tab"），因此页面的显示模式与是否发生过更新检查毫无关系。

若要使用 web.dev 所描述的方法查看更新状态，请使用浏览器提供的诊断页面：

- 在桌面版 Chrome（85+）中，`chrome://web-app-internals` "包含设备上所有已安装
  PWA 的详细信息"，其中包括某个应用的清单上次检查时间及更新频率，出自 web.dev。
- 在 Android 版 Chrome 中，`about://webapks` 为已安装的 WebAPK 提供同类详细信息，
  并显示一个 "Update Status"（更新状态）字段，出自 web.dev。

手动打开相应的内部页面，即可查看 web.dev 所描述的清单更新信息。

## 实践清单

- 不要重命名或移动清单文件——web.dev 自身的提醒指出，这样做"可能导致浏览器无法
  更新你的 PWA"。
- 在多数情况下，变更会"在一两天内"生效，因为 web.dev 说明两个平台都以大约 24
  小时为周期检查，而不是立即生效。
- 桌面端目前完全不会应用图标变更；只有 Android 端重建 WebAPK 时才会采用新的
  `icons` 列表。
- 在桌面端修改 `start_url` 只有在清单同时声明了 `id` 时才会生效——参见下方的
  `id` 参考文档。
- 可使用 `chrome://web-app-internals`（桌面端，Chrome 85+）查看清单上次更新的
  时间及更新频率，或使用 `about://webapks`（Android）查看更新状态，以测试更新
  行为。

## 延伸阅读

- [Web app manifest id：稳定的 PWA 身份标识](/zh/reference/manifest/id/)
- [Manifest start_url](/zh/reference/manifest/start-url/)