跳转到内容

平台 · 平台

桌面上的 PWA

发布于

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

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

在 Chrome 与 Edge 中,提示位于地址栏:站点满足可安装性条件且尚未被该浏览器安装时,地址栏会出现安装图标,点击后显示确认框(Installing and uninstalling web apps,MDN)。具体标签(英文界面):

  • Chrome:地址栏右端的 Install 按钮;或对任何页面(有没有 manifest 都行)用 More > Cast, save, and share > Install page as app…(Chrome 帮助)。
  • Edge:地址栏中的 App available 图标,然后 Install;安装后的对话框提供 Pin to taskbar、Pin to Start 与 Auto-start on device login(Use Progressive Web Apps in Microsoft Edge,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,MDN)。standalone 给出一个没有地址栏的系统窗口;它仍是浏览器窗口,背后是执行安装的浏览器的引擎、profile 与扩展。Chromium 104 加入了 "display_override": ["window-controls-overlay"],它去掉标题栏并让页面绘制到标题栏区域,仅限桌面操作系统(Customize the window controls overlay of your PWA’s title bar,web.dev)。

{
"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 帮助)。

桌面版 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,web.dev)。Chrome 85 起可用的 chrome://web-app-internals 列出已安装应用的 manifest 状态与上次更新检查时间。

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

Window.matchMedia() 求值 display-mode 媒体特性,它反映的是正在使用的模式,而非请求的模式(display-mode,MDN):

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 的浏览器不会把页面运行在应用窗口里。

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

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

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

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

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

规范

规范状态
无。