Manifest · 清单成员
scope 清单成员
发布于 更新于
scope 是一个 URL 字符串,指定已安装 Web 应用的导航范围:哪些页面可以获得没有浏览器控件的
应用式窗口。一个 URL 与 scope URL 同源、且路径以 scope URL 的路径开头时,就在范围内;其他页面
都在范围之外,仍然可以访问,但浏览器会恢复自己的界面来提示用户。
Chrome 73(Android 与桌面端)、Edge 79、Samsung Internet 6.2、iOS 上的 Safari 16.4 与 macOS
上的 Safari 17 会把该成员应用到已安装应用(BCD html.manifest.scope)。桌面端 Firefox 157 没有
基于清单的安装路径,这个值在那里没有消费者。在 Android 上,同一个字符串还决定已安装的 WebAPK
会从其他应用接管哪些链接。
- 类型:持有 URL 的字符串,绝对或相对均可;相对值相对于清单文件的 URL 解析,而不是文档的 URL。
- 默认值:去掉文件名、查询串与片段后的
start_url。start_url为/app/index.html?user=1#home时,有效 scope 是/app/。 - 示例值:
"/app/"。
两条规则会让该成员被丢弃并回到默认值。scope 必须与文档同源,否则记录
property 'scope' ignored, should be same origin as document.;start_url 必须位于 scope 之内,否则记录
property 'scope' ignored. Start url should be within scope of scope URL.。
两条消息都来自 Chromium 的 manifest_parser.cc。
匹配是对路径做纯字符串前缀比较,而不是目录判断。"/app" 既匹配 /app/,也匹配 /app-admin/
与 /application.html;以 / 结尾才能把范围限定在一个目录内。scope 不是安全边界:范围外导航
从不被拦截;Service Worker 的 scope 是在 register() 时另行设定的值(MDN,
ServiceWorkerRegistration.scope),可以比清单的 scope 更宽或更窄。
范围外页面的呈现方式因平台而异。Android 上的 Chrome 以类似自定义标签页的视图打开页面,顶部显示
URL;桌面端的 Chrome 与 Edge 加一条带来源和“在浏览器中打开”控件的工具栏;iOS 上的 Safari 16.4
在主屏幕应用内显示一条横幅,而不是完整地址栏(BCD 注记)。跨源页面只能通过
scope_extensions 纳入范围。
每个示例都把一份清单和它在页面层面造成的结果放在一起。
把应用限定在子路径下
Section titled “把应用限定在子路径下”一个部署在 /app/ 下的仪表盘,站点的营销页面在根路径。指向 /pricing/ 的链接在应用窗口内打开,
但浏览器控件恢复显示,访问者能看出自己已经离开了应用。
{ "name": "Ledger", "start_url": "/app/", "scope": "/app/", "display": "standalone"}结尾的斜杠很重要:"scope": "/app" 还会把 /app-status/ 与 /apply.html 也划进来,因为匹配是
路径前缀比较。
让默认 scope 从带查询串的 start_url 推导出来
Section titled “让默认 scope 从带查询串的 start_url 推导出来”一份用查询串标记启动来源、但没有声明 scope 的清单。浏览器从 start_url 去掉文件名、查询串与
片段,于是有效 scope 是 /app/,整个目录都在范围内,包括用户通过导航到达的、不带标记的 /app/。
{ "name": "Ledger", "start_url": "/app/index.html?source=homescreen", "display": "standalone"}如果同一份清单写了 "start_url": "/app/index.html?source=homescreen" 和
"scope": "/dashboard/",scope 会被丢弃(起始 URL 不在其中),有效 scope 仍是 /app/;这个错误
除了上面引用的 DevTools 那一行之外没有任何提示。
在运行时检测范围外环境
Section titled “在运行时检测范围外环境”清单的 scope 不暴露给脚本,但 display-mode 媒体特性会报告当前页面是否带着浏览器界面显示。在
已安装应用里,这意味着页面在范围之外(或者用户在标签页里打开了它);在没有该特性的引擎里查询
什么都不匹配,代码走与浏览器标签页相同的回退分支。
function isWithinScope(target, scope) { const t = new URL(target, location.href); const s = new URL(scope, location.href); return t.origin === s.origin && t.pathname.startsWith(s.pathname);}
const APP_SCOPE = '/app/';const inAppWindow = matchMedia('(display-mode: standalone)').matches;
if (!inAppWindow || !isWithinScope(location.href, APP_SCOPE)) { // 浏览器标签页、不支持的引擎或范围外页面:显示完整的站点页头。 document.documentElement.dataset.chrome = 'site';} else { document.documentElement.dataset.chrome = 'app';}把 APP_SCOPE 放进与清单构建共享的同一个常量里,两者才不会漂移;它们不一致时浏览器不会给出
任何警告。
- start_url 清单成员
- scope_extensions 清单成员
- display 清单成员
- Service Worker 注册与作用域
- Chrome 与 Android 上的 PWA(WebAPK、TWA)
- Web Application Manifest: scope member(w3.org)
- WebAPKs on Android(web.dev)
- scope(developer.mozilla.org)
规范
| 规范 | 状态 |
|---|---|
| Web 应用清单:scope | W3C |
| Web Application Manifest: within scope | W3C |
- 图例
- 支持
- 部分支持
- 需开启标志
- 不支持
- 未知
| 浏览器 / 平台 | 支持 | 版本 | 置信度 | 来源 | 备注 |
|---|---|---|---|---|---|
| Chrome (Android) | 支持 | 73 | 中 | 来源 | — |
| Chrome (Desktop) | 支持 | 73 | 中 | 来源 | — |
| Edge (Desktop) | 支持 | 79 | 中 | 来源 | — |
| Safari (iOS) | 支持 | 16.4 | 中 | 来源 | 1 |
| Safari (macOS) | 支持 | 17 | 中 | 来源 | 2 |
| Firefox (Desktop) | 不支持 | — | 中 | 来源 | 3 |
| Samsung Internet | 支持 | 6.2 | 中 | 来源 | — |
- 对主屏幕 Web 应用生效;导航到范围外时显示一条横幅,而不是完整地址栏。
- 适用于添加到程序坞的 Web 应用。
- 没有基于 manifest 的安装路径,因此 scope 不生效。
生态与商业政策
| 主体 | 类型 | 场景 | 状态 | 赞助 | 备注 |
|---|---|---|---|---|---|
| Google Play (TWA) | distribution_channel | Google Play TWA | 支持 | 否 | assetlinks.json 的源必须与 manifest scope 的源一致,否则 TWA 会退化为带浏览器外框的 Custom Tab。 |
| Microsoft Store (PWA) | distribution_channel | Microsoft Store | 支持 | 否 | scope 定义了商店审核人员在提交时预览的应用内边界。 |