# Web app manifest id：PWA 的稳定身份

> manifest 的 id 成员让已安装 PWA 的身份独立于 start_url，URL 变化时也不会产生重复安装。

**一句话：** `id` 是标识你 web 应用的字符串。由于它**独立于 `start_url`**，你以后可以更改应用
的启动位置，而浏览器不会把它当成另一个应用。

## 为什么需要 id

过去并没有一种统一定义的方式来标识已安装的 web 应用：有些浏览器从 `start_url` 推导身份，
另一些则使用 manifest 文件的路径。这让启动 URL 实际上身兼身份之职，于是更改 `start_url`
可能导致浏览器把该 manifest 视为描述一个**不同**的应用，从而创建重复安装，而非更新已有安装。

`id` 成员将此标准化。它提供一个独立于 `start_url` 的显式身份，使启动 URL 与持久身份不再是
同一个值。

## id 如何被解析

- `id` 是一个字符串，作为 URL **相对于 `start_url` 的源（origin）** 解析。因此对于
  `start_url` 在 `https://example.com` 上的应用，`"id": "/?source=pwa"` 解析为
  `https://example.com/?source=pwa`。
- 解析后的值成为应用的身份，浏览器据此判断某个 manifest 是否描述一个先前已处理过的应用。
- 若 `id` **被省略或无法解析**，身份默认为 `start_url`。正是这个默认值把身份与启动 URL 绑在
  一起。
- 由于 `id` 相对于 `start_url` 的源解析，它只能标识同一源内的应用；它无法指向另一个站点。

## 应当设成什么

- **从首个版本就设置 `id`。** 由于省略的 `id` 默认为 `start_url`，以后添加或更改 `id` 可能
  改变计算出的身份，因此在任何人安装之前就选定它，可避免扰动现有安装。
- **保持简短且稳定。** 常见选择是 `"id": "/"` 或一个标记，如 `"id": "/?homescreen=1"`。具体
  值无关紧要，只要它永不改变。
- **把 `id` 当作永久的。** 更改它会改变应用的身份，而这正是 `id` 存在所要避免的情况。

```json
{
  "name": "OpenPWA Demo",
  "start_url": "/app/?utm_source=pwa",
  "id": "/?homescreen=1",
  "display": "standalone"
}
```

在这份 manifest 中，应用从 `/app/?utm_source=pwa` 启动，但其身份是固定的 `/?homescreen=1`。
你以后可以移动启动路径而不改变身份。

## 浏览器与生态支持

`id` 成员定义于 Web App Manifest 规范。Chrome 自 Chrome 96 起支持它。不处理 `id` 的浏览器
保持其既有的身份行为，因此在不支持之处声明 `id` 不会破坏任何东西。

## 实践清单

- [ ] 在首次公开安装之前，为 manifest 添加 `id`。
- [ ] 选择一个简短、永久的值（`/` 或固定的标记查询）并记录下来。
- [ ] 保持 `id` 稳定，以便你能独立地更改启动 URL（`start_url`）。
- [ ] 上线后避免更改 `id`——它会改变应用的身份。
- [ ] 记住 `id` 相对于 `start_url` 的源解析，因此一个前导 `/` 就够了。
- [ ] 在 Chromium DevTools → Application → Manifest 中核对计算出的 app id 是否符合预期。