# 桌面上的 PWA

> Chrome 与 Edge 如何从桌面地址栏安装 PWA、manifest 的 display 回退链能给你什么，以及为什么每个浏览器各留一份副本。

**一句话：** 根据 MDN，在桌面设备上安装 PWA 比添加书签"更深入地把这个 Web 应用集成
到用户设备中"——它可能让应用拥有"自己的独立窗口"，而在大多数桌面浏览器上，安装提示
出现在地址栏而不是菜单里。

## 从桌面地址栏安装

根据 MDN，"在桌面版 Chrome 和 Edge 中，当用户导航到某个页面时，如果该页面是 PWA 且
浏览器尚未安装它，地址栏中就会出现一个安装图标"。选择该图标后，"浏览器会显示提示，
询问用户是否要安装该 PWA；如果用户接受，PWA 就被安装"。MDN 还补充说"无论是哪个浏览器
或操作系统，安装都需要被确认"。

根据 MDN，安装完成后"该 PWA 的行为将与操作系统上已安装的其他应用一样"——MDN 自己的
例子是 macOS，在那里"图标会出现在 Dock 中，并且拥有与其他应用相同的图标选项"。MDN
还指出"该应用会出现在操作系统存放其他应用的位置，位于该浏览器专属的文件夹中"，并且
点击图标"会打开该 PWA，即使用户处于离线状态"。

## 桌面上的安装支持情况

根据 MDN，"所有现代桌面和移动设备都支持安装"，但"浏览器能否在某个操作系统上安装该
PWA，取决于浏览器/操作系统的组合"。MDN 的说法是：

- "大多数浏览器都支持在所有操作系统上安装 PWA——ChromeOS、macOS、Windows、Android、
  Linux 等——或直接支持，或在安装了扩展之后支持。"
- "Firefox 需要一个 PWA 扩展。"
- "在 macOS 14（Sonoma）之前，PWA 可以从**除** Safari 以外的任何浏览器安装到
  macOS"，而"在 macOS 14.0 或更高版本……可以从任何支持的浏览器安装 PWA"。

## 选择窗口形态：`display` 成员

根据 MDN，"`display` manifest 成员用于指定你为该 Web 应用首选的显示模式"，而"显示
模式决定了应用在操作系统上下文中启动时，向用户展示多少浏览器 UI"。它的关键字取值为
`fullscreen`、`standalone`、`minimal-ui` 和 `browser`；根据 MDN，"如果未指定，将使用
默认值 `browser`"。

对于桌面应用窗口，`standalone` 就是 MDN 所描述的、让"应用的外观和体验像一个独立的
原生应用"的取值，它"可以包括应用拥有不同的窗口以及在应用启动器中拥有自己的图标"，
浏览器会排除"诸如地址栏之类的 UI 元素"。

```json
{
  "name": "HackerWeb",
  "short_name": "HackerWeb",
  "start_url": "/index.html",
  "display": "standalone",
  "background_color": "white",
  "description": "A readable Hacker News app",
  "icons": [
    {
      "src": "images/icons/homescreen192.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ]
}
```

根据 MDN，如果浏览器"不支持所指定的显示模式……它会遵循一条预定义的回退链：
`fullscreen` → `standalone` → `minimal-ui` → `browser`"。

## 检测与回退

根据 MDN，"`display-mode` 媒体特性可用于根据当前的 `display` 模式来配置应用的样式和
其他行为"，而且——这一点很重要——"`display-mode` 媒体特性的值反映的是浏览器实际使用
的 `display` 模式。它可能与 manifest 中请求的模式不同，因为浏览器可能不支持所请求的
模式"。根据 MDN，`Window.matchMedia()`"返回一个新的 `MediaQueryList` 对象，可用于判断
文档是否匹配该媒体查询"，这就是从脚本中读取该媒体特性的方式：

```js
function isStandaloneDisplayMode() {
  if (!('matchMedia' in window)) {
    // 回退：matchMedia 不可用——在这里无法检测 `standalone`。
    return false;
  }
  return window.matchMedia('(display-mode: standalone)').matches;
}

if (isStandaloneDisplayMode()) {
  // 当前使用的显示模式是 `standalone`。
} else {
  // 当前使用的显示模式不是 `standalone`。
}
```

同样的检查也可以从 CSS 里做，这是 MDN 记录的形式：

```css
@media (display-mode: standalone) {
  body {
    background-color: #f0f0f0; /* Light grey background for standalone mode */
  }
}
```

## 实用检查清单

- [ ] **你请求的窗口形态并不总是你得到的那个。** 除了回退链之外，MDN 还说明浏览器
      "可能出于安全原因覆盖该显示模式，或者为用户提供切换到其他 `display` 模式的
      途径"——所以请在运行时读取 `display-mode`，而不要假设 manifest 里的值生效。
- [ ] **独立窗口仍然是浏览器窗口。** 根据 MDN，启动后的 PWA"可以显示在自己的独立
      窗口中（不带完整的浏览器 UI），但它实际上仍然运行在浏览器窗口里，即使地址栏
      或返回按钮之类常见的浏览器 UI 元素并不可见"。
- [ ] **不同浏览器的安装不会合并。** 根据 MDN，"由某个浏览器安装的 PWA 仍然专属于
      该浏览器"，所以从第二个浏览器再安装同一个应用会得到两个应用：MDN 的例子是用
      Edge 安装之后，"当你访问该站点时 Edge 会提示你打开该 PWA，而 Chrome 会继续
      提示你安装该应用"。根据 MDN，"当一个 PWA 的多个实例同时打开时，来自不同浏览器
      安装的实例之间不共享数据"。
- [ ] **卸载同样与浏览器绑定。** 根据 MDN，"卸载 PWA 的方式取决于当初用来安装它的
      浏览器"；在 Edge 中，已安装的 PWA"可以通过访问 `edge://apps` 列出并管理"，在
      Chrome 中则通过访问 `chrome://apps`。
- [ ] **不要向 Firefox 用户承诺一键安装。** 根据 MDN，Firefox 需要一个 PWA 扩展，
      所以 Chrome 和 Edge 展示的那个地址栏安装图标并不属于那里的流程。

## 下一步

- [Windows 上的 PWA](/zh/reference/platforms/windows/)——本站的 Windows 平台条目。
- [macOS Safari 上的 PWA](/zh/reference/platforms/macos-safari/)——本站的 macOS
  Safari 平台条目。
- [桌面安装](/zh/reference/installation/desktop-install/)——本站的安装条目。