跳转到内容

安装 · 概念

安装后的应用快捷方式

发布于

应用快捷方式是 manifest shortcuts 成员中的条目,用户右键或长按已安装 web 应用的图标时由操作系统列出;菜单属于图标,所以应用安装之前不存在任何快捷方式。Android 上的 Chrome 85、桌面端 Chrome 与 Edge 96、Samsung Internet 14、macOS 上的 Safari 17.4 会读取该成员;iOS 上的 Safari 与 Firefox 忽略它(BCD html.manifest.shortcuts)。

安装时,浏览器把 shortcuts 复制进平台自己的快捷方式机制:Windows 跳转列表(右键任务栏或开始菜单图标)、macOS Dock 图标的上下文菜单、ChromeOS 任务栏菜单,或 Android 的启动器快捷方式(长按主屏幕或应用抽屉图标)。这些条目是静态副本,manifest 改动要等浏览器下一次 manifest 更新检查后才会反映到菜单里,而不是下一次页面加载。

每个快捷方式对象包含 name(必需)、url(必需),以及可选的 short_name、description 与 icons。url 相对 manifest 自身的 URL 解析,而不是相对页面或 start_url:位于 /dashboard/manifest.json 的 manifest 写 "url": "../projects" 会打开 /projects。解析后的 URL 必须落在 manifest scope 内;超出 scope 的条目会被浏览器直接丢弃而不报错。规范没有数量上限,但 Windows 跳转列表与 Android 启动器只显示前几项,所以最常用的操作应排在数组最前。

快捷方式一旦打开就没有任何特殊之处:应用在它的 standalone 窗口中收到一次指向快捷方式 URL 的普通导航。因此在不支持该成员的地方,快捷方式不花任何代价(同样的 URL 在应用内仍可作为链接使用);在支持的地方,则多了一个启动器级别的入口。

manifest 片段声明两个快捷方式;脚本展示应用如何得知由哪一个启动,以及在不支持该成员时会怎样。

声明在应用 scope 内解析的快捷方式

Section titled “声明在应用 scope 内解析的快捷方式”

manifest 位于 /app/manifest.webmanifest,所以相对 URL 解析到 /app/ 之下。每项带 ?source=shortcut 查询参数,便于应用归因启动来源。

{
"name": "Calendar",
"start_url": "/app/",
"scope": "/app/",
"display": "standalone",
"shortcuts": [
{
"name": "New event",
"short_name": "New",
"description": "Create an event starting now",
"url": "new-event?source=shortcut",
"icons": [{ "src": "icons/new-event-96.png", "sizes": "96x96", "type": "image/png" }]
},
{
"name": "Today",
"url": "today?source=shortcut",
"icons": [{ "src": "icons/today-96.png", "sizes": "96x96", "type": "image/png" }]
}
]
}

若改写成 "url": "/new-event",它会解析到 /app/ 之外,浏览器会悄悄丢掉这个快捷方式;图标保持 96×96 px 与 Chrome 文档中 Android 快捷方式图标的尺寸一致。

判断由哪个快捷方式启动,并为无快捷方式的浏览器回退

Section titled “判断由哪个快捷方式启动,并为无快捷方式的浏览器回退”

应用在启动时读取 location.pathname 与 source 查询参数。在不支持 shortcuts 的地方(iOS 上的 Safari、Firefox),同样的 URL 仍可作为应用内链接访问,所以应用改在自己的菜单里展示它们。

const url = new URL(location.href);
const fromShortcut = url.searchParams.get('source') === 'shortcut';
if (fromShortcut && url.pathname.endsWith('/new-event')) {
openEventEditor({ startsAt: Date.now() });
analytics.track('launch_shortcut', { shortcut: 'new-event' });
}
// 回退:iOS Safari 与 Firefox 没有启动器菜单,把同样的操作放进应用内。
// `display-mode` 能告诉我们应用是否以安装态运行。
const installed = matchMedia('(display-mode: standalone)').matches || navigator.standalone === true;
if (!installed || /iPhone|iPad|Firefox/.test(navigator.userAgent)) {
renderQuickActions([
{ label: 'New event', href: '/app/new-event?source=menu' },
{ label: 'Today', href: '/app/today?source=menu' },
]);
}

source 查询参数是唯一可靠的归因手段:启动器发起的导航没有 referrer,document.referrer 无法区分快捷方式与手动输入的 URL。

规范

规范状态
无。