# 添加应用快捷方式

> 在 PWA manifest 中添加 shortcuts 条目，让已安装应用的图标提供快捷操作，保持每个 URL 在 scope 内，并在应用内镜像这份菜单。

import CompatTable from '@components/CompatTable.astro';

完成本指南后，在 Windows 上右键点击已安装应用的任务栏图标，或在 Android 上长按它的启动器图标，
会弹出一个快捷操作菜单，直接跳到应用内的某个页面。manifest 的 `shortcuts` 成员声明这些操作；
菜单由操作系统绘制。

你需要一个可安装的 PWA（见[让它可安装](/zh/guides/installable/)），因为菜单只对已安装的应用显示；
还需要两到四个用户常去的目的地。这是一项 Chromium 功能（Windows、macOS、ChromeOS 与 Android 上的
Chrome 与 Edge）；版本见第 4 步的表格。

## 1. 在 manifest 中声明 shortcuts

每一项都需要 `name` 与 `url`；`short_name`、`description` 与 `icons` 可选。按重要性排列数组，
因为浏览器按 manifest 顺序显示条目，并按宿主操作系统的上限截断列表。

```json
{
  "name": "Ledger",
  "start_url": "/app/",
  "scope": "/app/",
  "display": "standalone",
  "icons": [{ "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png" }],
  "shortcuts": [
    {
      "name": "New invoice",
      "short_name": "New",
      "description": "Create a new invoice",
      "url": "/app/invoice/new?source=shortcut",
      "icons": [{ "src": "/icons/shortcut-new-192.png", "sizes": "192x192", "type": "image/png" }]
    },
    {
      "name": "Dashboard",
      "url": "/app/dashboard?source=shortcut",
      "icons": [{ "src": "/icons/shortcut-dashboard-192.png", "sizes": "192x192", "type": "image/png" }]
    }
  ]
}
```

每个快捷方式用一张 192×192 的 PNG，或者用 48 dp 系列（36、48、72、96、144、192）获得逐像素精确的渲染；
Chromium 不支持 SVG 快捷方式图标，而 macOS 的 Dock 菜单根本不显示图标，所以名称必须自己站得住。
`?source=shortcut` 参数可以让分析工具统计从菜单发起的启动。

## 2. 让每个快捷方式的 URL 都保持在 scope 内

快捷方式的 `url` 必须位于 manifest 的 `scope` 之内；超出 scope 的 URL 会被丢弃。相对 URL 相对于
manifest 文件的位置解析，而不是相对于页面，所以位于 `/app/manifest.webmanifest` 的 manifest 里写
`"url": "../projects"` 会打开 `/projects`，这超出了 `/app/`，会被忽略。目的地不必能从应用内导航到达；
只要留在 scope 内，一个仅通过快捷方式进入的入口也是允许的。

## 3. 在应用内镜像这份菜单

没有任何 JavaScript API 能报告当前浏览器与操作系统是否会绘制快捷方式菜单，W3C 规范把呈现方式与数量都
交给用户代理决定。唯一可靠的回退是无条件的：把同样的操作也渲染成应用内菜单，让没有快捷方式的浏览器
上的用户也有等效路径。页面能检测的是自己的 manifest，这对保持两份菜单同步很有用。

```js
async function shortcutsFromManifest() {
  const link = document.querySelector('link[rel="manifest"]');
  if (!link) return [];
  try {
    const manifest = await fetch(link.href).then((response) => response.json());
    return Array.isArray(manifest.shortcuts) ? manifest.shortcuts : [];
  } catch {
    return [];
  }
}

shortcutsFromManifest().then((shortcuts) => {
  const menu = document.querySelector('#quick-actions');
  menu.replaceChildren(
    ...shortcuts.map((shortcut) => {
      const link = document.createElement('a');
      link.href = shortcut.url;
      link.textContent = shortcut.name;
      return link;
    }),
  );
});
```

## 4. 安装并打开快捷方式菜单

安装应用，然后在 Windows 上右键点击任务栏图标，在 macOS 上右键点击 Dock 图标，在 Android 上长按启动器
图标。第 1 步的条目按顺序出现；选中其中一项会在该 URL 打开应用。Chrome DevTools 在 **Application** >
**Manifest**（英文界面）下以 **Shortcut #1**、**Shortcut #2** 等形式显示解析后的条目，这是检查图标是否
能加载的最快方式。改动会在浏览器的 manifest 更新检查时到达现有安装，Chrome 把这个检查限制为每天一次。

:::observed
Windows 上的 Chrome 与 Edge 最多显示 10 条快捷方式；Android 版 Chrome 显示 3 条，因为 Chrome 92 在启动器
菜单里加入了自己的 **Site settings** 条目（英文界面），占掉了 Android 原本提供的四个位置之一。
在 manifest 里声明第五条快捷方式在这两个平台上都不会有任何变化：多出的条目被静默截断，这正是顺序重要的原因。
:::

<CompatTable feature="manifest-shortcuts" />

## 另请参阅

- [Manifest 快捷方式（shortcuts）](/zh/reference/manifest/shortcuts/)
- [安装后的应用快捷方式](/zh/reference/installation/install-shortcuts/)
- [manifest: shortcuts 支持情况](/zh/compatibility/manifest-shortcuts/)
- [Get things done quickly with app shortcuts](https://web.dev/articles/app-shortcuts)（web.dev）
- [Web Application Manifest: shortcuts member](https://www.w3.org/TR/appmanifest/#shortcuts-member)（w3.org）

← 返回[指南](/zh/guides/)总览。