跳转到内容

Manifest · 清单成员

widgets 清单成员

发布于

widgets 是一组小组件定义,已安装的 PWA 用它向操作系统的小组件界面提供内容。每个定义指明一个 Adaptive Cards 模板和一个 JSON 数据 URL;浏览器绘制卡片,应用的 Service Worker 响应小组件生命周期事件 来填充和刷新它,全程不需要打开任何页面。

Windows 11 上的 Microsoft Edge 108 及之后版本是唯一实现,目标是 Windows 11 小组件面板 (Microsoft Edge 文档,“Build PWA-driven widgets”)。该成员来自微软的说明文档,不是 W3C 或 WICG 草案; Chrome 155、Firefox 157 与 Safari 27 在解析时将其丢弃。

  • 类型:小组件定义对象数组。必填键:name、description、tag(Service Worker 用来指代该小组件的 字符串)、ms_ac_template(Adaptive Cards 模板的 URL)与 data(模板绑定的 JSON 的 URL)。可选键: short_name、template(在 Edge 中仅供参考)、type(数据的 MIME 类型,默认 application/json)、 icons、screenshots、backgrounds、auth(布尔值)与 update(刷新周期,单位为秒)。
  • 默认值:缺省。没有该成员,应用不会在小组件面板提供任何内容;缺少 tag 或 ms_ac_template 的条目 不会被提供。
  • 示例值:[{ "name": "待办任务", "tag": "tasks", "ms_ac_template": "/widgets/tasks.json", "data": "/widgets/tasks-data.json" }]。

安装应用只是把它的小组件列进面板的 Add widgets 选择器。用户添加后小组件才激活,此时 Service Worker 收到 widgetinstall 事件;Worker 随后调用 self.widgets.updateByTag(tag, { template, data }) 完成渲染。 其余事件有 widgetuninstall、widgetresume(面板重新可见)与 widgetclick(用户触发了 Adaptive Cards 动作,动作名在 event.action 上)。Edge 还提供 self.widgets.getByTag()、getByInstanceId() 与 matchAll() 用于枚举已安装的小组件。

示例描述从 https://tasks.example/ 安装的应用上的一个任务列表小组件。

声明小组件及其模板、数据与刷新周期

Section titled “声明小组件及其模板、数据与刷新周期”

tag 是每次 Service Worker 调用的键,应在各版本间保持稳定。update: 900 请求 Edge 在小组件位于面板上时 每十五分钟重新拉取一次 data。

{
"widgets": [
{
"name": "待办任务",
"short_name": "任务",
"description": "一眼看到你的待办任务",
"tag": "open-tasks",
"template": "open-tasks",
"ms_ac_template": "/widgets/open-tasks.ac.json",
"data": "/widgets/open-tasks-data.json",
"type": "application/json",
"update": 900,
"icons": [{ "src": "/widgets/icon-96.png", "sizes": "96x96" }],
"screenshots": [
{ "src": "/widgets/open-tasks-wide.png", "sizes": "600x400", "label": "列出三个任务的待办任务小组件" }
]
}
]
}

screenshots 条目会显示在选择器里,所以它应当呈现渲染后的卡片,而不是应用本身。

Service Worker 拉取小组件定义中指明的模板与数据,把两者交给 updateByTag()。同一个函数也在 widgetresume 时运行,这是面板隐藏期间数据过期后的刷新时机。

async function renderWidget(widget) {
const definition = widget.definition;
const template = await (await fetch(definition.msAcTemplate)).text();
const data = await (await fetch(definition.data)).text();
await self.widgets.updateByTag(definition.tag, { template, data });
}
self.addEventListener('widgetinstall', (event) => {
event.waitUntil(renderWidget(event.widget));
});
self.addEventListener('widgetresume', (event) => {
event.waitUntil(renderWidget(event.widget));
});

Edge 在 event.widget.definition 上暴露定义,清单键被转换为驼峰命名,所以模板 URL 读作 msAcTemplate。

self.widgets 只存在于实现了小组件的浏览器,所以跨浏览器共用的 Service Worker 要对每次调用加保护。 widgetclick 处理函数收到 Adaptive Cards 模板中声明的动作名,可以就地更新卡片。

if ('widgets' in self) {
self.addEventListener('widgetclick', (event) => {
if (event.action !== 'complete-task') return;
event.waitUntil(
fetch('/api/tasks/complete', { method: 'POST', body: JSON.stringify(event.data) })
.then(() => renderWidget(event.widget)),
);
});
} else {
// 此浏览器没有小组件界面;应用只保留页内的任务列表。
}

在 Edge 之外,else 分支就是全部:清单条目无效,Worker 不注册任何监听器。

规范

规范状态
PWA-driven Widgets explainer社区草案