# 桌面上的 PWA

> Chrome、Edge 与 Safari 如何在桌面操作系统上安装 PWA、manifest 的 display 回退链能给你什么，以及为什么每个浏览器各留一份副本。

在 Windows、macOS、Linux 与 ChromeOS 上，PWA 从浏览器安装到一个独立窗口中，并出现在操作系统列出应用的地方；执行安装的浏览器拥有这份副本：Chrome、Edge 与 Safari 各自安装、更新、卸载自己的实例，彼此互不可见。

## 工作原理

桌面安装是叠加在操作系统之上的浏览器功能，所以入口、窗口外观与卸载路径按浏览器各不相同，而驱动它们的 manifest 是同一份。

### 各浏览器的安装支持

在 Chrome 与 Edge 中，提示位于地址栏：站点满足可安装性条件且尚未被该浏览器安装时，地址栏会出现安装图标，点击后显示确认框（[Installing and uninstalling web apps](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Installing)，MDN）。具体标签（英文界面）：

- Chrome：地址栏右端的 **Install** 按钮；或对任何页面（有没有 manifest 都行）用 **More** > **Cast, save, and share** > **Install page as app...**（[Chrome 帮助](https://support.google.com/chrome/answer/9658361)）。
- Edge：地址栏中的 **App available** 图标，然后 **Install**；安装后的对话框提供 **Pin to taskbar**、**Pin to Start** 与 **Auto-start on device login**（[Use Progressive Web Apps in Microsoft Edge](https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps/ux)，Microsoft Learn）。
- Safari：macOS 14（Sonoma）搭配 Safari 17 及之后，**File** > **Add to Dock...**，有没有 manifest 的站点都可以；macOS 14 之前，Safari 是 macOS 上唯一不能安装的浏览器（MDN）。
- Firefox：桌面版没有由 manifest 驱动的安装；MDN 指向一个第三方扩展。

### 你得到的窗口

manifest 的 `display` 成员请求 `fullscreen`、`standalone`、`minimal-ui` 或 `browser`（缺省时为默认值）。不实现所请求模式的浏览器会沿回退链 `fullscreen` → `standalone` → `minimal-ui` → `browser` 下降，可能出于安全原因覆盖该模式，也可能让用户自行切换（[Manifest display](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/display)，MDN）。`standalone` 给出一个没有地址栏的系统窗口；它仍是浏览器窗口，背后是执行安装的浏览器的引擎、profile 与扩展。Chromium 104 加入了 `"display_override": ["window-controls-overlay"]`，它去掉标题栏并让页面绘制到标题栏区域，仅限桌面操作系统（[Customize the window controls overlay of your PWA's title bar](https://web.dev/articles/window-controls-overlay)，web.dev）。

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

### 每个浏览器一份副本

安装属于执行安装的浏览器。先从 Edge 安装同一个站点，再从 Chrome 安装，你会得到两个应用，各自放在该浏览器在操作系统应用目录下的专属文件夹里，Cookie、存储与 Service Worker 互不共享；Edge 会提示打开它的副本，而 Chrome 继续提示安装（MDN）。管理页面也是按浏览器分开的：Edge 用 `edge://apps`，Chrome 用 `chrome://apps`。在 Chrome 中卸载是在应用窗口内进行的：**More** > **Uninstall [app name]** > **Remove**（Chrome 帮助）。

### 桌面上的 manifest 更新

桌面版 Chrome 在应用启动时，如果浏览器启动以来或最近 24 小时内没有检查过，就会重新拉取 manifest；`name`、`short_name`、`display`、`scope`、`shortcuts`、`start_url`（仅当 manifest 设有 `id`）、`theme_color` 或 `file_handlers` 的变化会在所有应用窗口关闭后应用；`icons` 的变化在桌面上不会应用，已把应用切换为在标签页中打开的用户，在 `display` 变化后也保留自己的选择（[How Chrome handles updates to the web app manifest](https://web.dev/articles/manifest-updates)，web.dev）。Chrome 85 起可用的 `chrome://web-app-internals` 列出已安装应用的 manifest 状态与上次更新检查时间。

## 示例

两段代码读取的都是浏览器实际应用的模式，它可能与 manifest 请求的不同。

### 在脚本中按实际显示模式分支

`Window.matchMedia()` 求值 `display-mode` 媒体特性，它反映的是正在使用的模式，而非请求的模式（[`display-mode`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/display-mode)，MDN）：

```js
function isStandaloneDisplayMode() {
  if (!('matchMedia' in window)) {
    return false; // 不支持媒体查询：当作普通标签页处理
  }
  return window.matchMedia('(display-mode: standalone)').matches;
}

if (isStandaloneDisplayMode()) {
  document.querySelector('#install-banner').hidden = true;
} else {
  document.querySelector('#install-banner').hidden = false;
}
```

回退分支保持安装横幅可见，这是安全的默认值：没有 `matchMedia` 的浏览器不会把页面运行在应用窗口里。

### 用 CSS 为独立窗口设置样式

同一个媒体特性不需要脚本也能用，适合那些只有在没有地址栏时才有意义的间距：

```css
@media (display-mode: standalone) {
  body {
    padding-top: env(titlebar-area-height, 0px);
  }
}
```

`env(titlebar-area-height)` 只在 window controls overlay 下有定义；`0px` 默认值让这条规则在普通 `standalone` 下不产生影响。

## 实测行为

因为安装是按浏览器的，卸载对话框也是浏览器的而不是操作系统的，由它决定站点数据的去留。

:::observed
在 Windows、macOS、Linux 上的 Chrome（英文界面）中，应用窗口内的 **More** > **Uninstall [app name]** 打开一个对话框，确认按钮是 **Remove**，可选复选框的文字是「Also delete data from Chrome.」（Chrome 帮助，2026-10 读取）。不勾选时只卸载窗口，Cookie、IndexedDB 与 Service Worker 注册都会保留，下次在标签页里访问时，从 Service Worker 的角度看站点仍处于「已安装」状态。
:::

Edge 的对应入口在 `edge://apps`（**Details** > **Uninstall**），会提示是否一并删除应用历史与数据（Microsoft 支持）。保存状态的 PWA 应把重新安装当作可能的续接，而不是首次运行。

## 另请参阅

- [Installing and uninstalling web apps](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Installing)（developer.mozilla.org）
- [Use Progressive Web Apps in Microsoft Edge](https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps/ux)（learn.microsoft.com）
- [How Chrome handles updates to the web app manifest](https://web.dev/articles/manifest-updates)（web.dev）
- [桌面端 PWA 安装：Chrome、Edge 及更多](/zh/reference/installation/desktop-install/)
- [Manifest display：standalone 与 fullscreen](/zh/reference/manifest/display/)
- [display_override：选用 window-controls-overlay 与 tabbed 模式](/zh/reference/manifest/display-override/)
- [Windows 上的 PWA](/zh/reference/platforms/windows/)
- [macOS 上的 Safari PWA（Dock 应用）](/zh/reference/platforms/macos-safari/)
- [国内厂商浏览器](/zh/compatibility/cn-vendor-browsers/)