共用方式為


建置 PWA 驅動小工具

各種作業系統都有小工具儀錶板,可讓使用者讀取內容並執行工作。 其中的範例包括 Android 主畫面小工具、macOS 儀錶板和今日面板小工具、Apple Touch Bar、Samsung Daily Card、迷你應用程式小工具,以及智慧型手機監看應用程式小幫手。

在 Windows 11 上,小工具會出現在您從任務列左側開啟的 Widget 面板中:

Windows 11 中的 Widget 面板

在 Windows 11 中,漸進式 Web Apps (PWA) 可以定義小工具、更新小工具,以及處理它們內的用戶互動。

需要建置 PWA 的自定義小工具

現有的 PWA 無法直接依原樣放入小工具儀錶板中,就像您可以使用 Microsoft Edge 提要字段一樣。 相反地,您必須建置適用於小工具主機的自定義小工具體驗,該小工具主機目前是 Windows 11 小工具面板。 (未來可能會有其他小工具主機。) Windows 11 小工具面板需要使用調適型卡片範本而非 HTML 和 JavaScript 來建置小工具,因此小工具必須與應用程式 UI 的其餘部分分開設計。

另請參閱:

若要建置 PWA 驅動的小工具,並透過Microsoft存放區傳遞它,不需要C++/C# 程式代碼。 一旦您已產生小工具,而且可以從公用端點成功安裝和執行小工具,您就可以使用 PWABuilder.com 封裝應用程式,並將應用程式寄送至Microsoft存放區,而不需要任何其他程序代碼。 支援小工具的 PWA 必須可從公用端點安裝,因為 PWABuilder.com 不支援從 localhost 封裝應用程式。

另請參閱:

安裝 WinAppSDK 並啟用開發人員模式

若要在本機電腦上啟用開發和測試小工具:

  • 安裝 WinAppSDK 1.2

  • 在 Windows 11 中啟用開發人員模式:

    1. 啟 [設定]

    2. 在 [ 尋找設定] 文本框中,輸入 developer,然後按兩下 [ 使用開發人員功能]

    3. 開啟 開發者模式

      Windows 11 的開發人員設定

定義小工具

Widget 是使用指令清單成員在 PWA 指令清單檔案中 widgets 定義。 此指令清單成員是可包含多個小工具定義的陣列。

{
  "name": "PWAmp",
  "description": "A music player app",
  "icons": [
    { "src": "img/icon-96.png", "sizes": "96x96" },
    { "src": "img/icon-128.png", "sizes": "128x128" },
    { "src": "img/icon-256.png", "sizes": "256x256" },
    { "src": "img/icon-512.png", "sizes": "512x512" }
  ],
  "widgets": [
    /* widget definitions go here */
  ]
}

陣列中的 widgets 每個專案都包含數個字段,如下所示:

{
  ...
  "widgets": [
    {
      "name": "PWAmp mini player",
      "description": "widget to control the PWAmp music player",
      "tag": "pwamp",
      "template": "pwamp-template",
      "ms_ac_template": "widgets/mini-player-template.json",
      "data": "widgets/mini-player-data.json",
      "type": "application/json",
      "screenshots": [
        {
          "src": "./screenshot-widget.png",
          "sizes": "600x400",
          "label": "The PWAmp mini-player widget"
        }
      ],
      "icons": [
        {
          "src": "./favicon-16.png",
          "sizes": "16x16"
        }
      ],
      "auth": false,
      "update": 86400
    }
  ]
}

在上述範例中,音樂播放機應用程式會定義迷你播放機小工具。 Web 應用程式指令清單中的 Widget 定義具有下列必要和選擇性欄位:

欄位 描述 必要項目
name 小工具的標題,呈現給使用者。
short_name 名稱的替代簡短版本。
description 小工具用途的描述。
icons 要用於小工具的圖示陣列。 如果遺漏, icons 則會改用指令清單成員。 大於 1024x1024 的圖示會被忽略。
screenshots 顯示小工具外觀的螢幕快照陣列。 類似於指令screenshot清單成員platform螢幕快照專案的欄位支援 Windowsany 值。 大於 1024x1024 像素的影像會被忽略。 如需 Windows 11 小工具面板特定的螢幕快照需求,請參閱與小工具選擇器整合中的螢幕快照影像需求。
tag 用來參考 PWA 服務背景工作角色中小工具的字串。
template 用來在操作系統小工具儀錶板中顯示小工具的範本。 注意:此屬性目前僅供資訊使用且未使用。 請參閱 ms_ac_template 下方。
ms_ac_template 自定義調適型卡片範本的 URL,用來在作業系統小工具儀錶板中顯示小工具。 請參閱下面 的定義小工具範本
data 可找到要填入範本之數據的URL。 如果存在,則需要此 URL 才能傳回有效的 JSON。
type 小工具數據的MIME類型。
auth 布爾值,指出小工具是否需要驗證。
update 更新小工具的頻率,以秒為單位。 服務工作者中的程式代碼必須執行更新;Widget 不會自動更新。 請參閱 在運行時間存取小工具實例
multiple 布爾值,指出是否允許 Widget 的多個實例。 預設為 true

定義小工具範本

為了讓小工具能夠輕鬆地建立和適應各種操作系統小工具儀錶板,它們會使用範本來顯示。 樣本有兩種類型:

  • 一般範本,由其名稱使用 template 欄位定義。
  • 自定義範本,由其URL使用自定義範本欄位定義。

目前僅支援自定義調適型卡片範本。 調適型卡片是開放式卡片交換格式,可用來以通用且一致的方式交換UI內容。 請參閱 調適型卡片概觀

若要在 Windows 11 上定義自訂調適型卡片範本,請在 Web 應用程式指令清單中的小工具定義中使用 ms_ac_template 字段。 雖然 template 目前未使用 ,但它是必要的欄位。

{
  ...
  "template": "pwamp-template",
  "ms_ac_template": "widgets/mini-player.json",
  ...
}

ms_ac_template 值應該是範本檔案的有效 URL。

以下是調適型卡片範例:

{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "TextBlock",
      "size": "Medium",
      "text": "Now playing...",
      "horizontalAlignment": "Center"
    },
    {
      "type": "TextBlock",
      "spacing": "Large",
      "weight": "Bolder",
      "horizontalAlignment": "Center",
      "text": "${song}, by ${artist}",
    }
  ],
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.5"
}

若要深入瞭解,請參閱 調適型卡片範本化

接下來,您必須將數據系結至範本。

將數據系結至您的範本

此範本會宣告小工具的使用者介面。 然後,數據會填入此使用者介面。

若要將數據系結至您的範本,請使用 data 小工具定義中的欄位。 此欄位應設定為會傳回有效 JSON 數據的 URL。

在上一節中定義的範本包含兩個變數: songartist,其包含在系結表達式語法中:${}。 小工具定義中 URL 所 data 傳回的數據應該包含這些變數的值。

以下是 URL 可能傳回的 data 範例:

{
  "song": "I Will Always Love You",
  "artist": "Whitney Houston"
}

定義小工具動作

如果您想要讓小工具讓使用者執行工作,請定義支援動作的範本。

以下是自訂調適型卡片範本中定義的動作範例:

{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "TextBlock",
      "size": "Medium",
      "text": "Now playing...",
      "horizontalAlignment": "Center"
    },
    {
      "type": "TextBlock",
      "spacing": "Large",
      "weight": "Bolder",
      "horizontalAlignment": "Center",
      "text": "${song}, by ${artist}",
    }
  ],
  "actions": [
    {
      "type": "Action.Execute",
      "title": "Previous",
      "verb": "previous-song"
    },
    {
      "type": "Action.Execute",
      "title": "Next",
      "verb": "next-song"
    }
  ],
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.5"
}

verb請注意上述 JSON 範本中的欄位。 在您的服務背景工作程式代碼中處理小工具動作時,會使用它。 請參閱 處理小工具動作

在運行時間存取小工具實例

您可以存取小工具,並從 PWA 服務背景工作程式代碼加以更新。 在執行時間存取小工具在下列情況中很有用:

服務工作者可以存 self.widgets 取 物件和數個小工具事件,這些事件一起構成 API,可讓您在運行時間回應變更和存取小工具。

下列各節提供程式碼範例。 如需 API 的參考,請參閱 服務背景工作角色 API 參考

在安裝時轉譯小工具

安裝 PWA 時,應用程式在其指令清單中定義的小工具會新增至小工具儀錶板,但尚未安裝。 只有當使用者選擇從儀錶板新增小工具時,才會安裝小工具。

安裝小工具時,不會使用 ms_ac_template 小工具定義的 和 data 欄位自動轉譯。

若要轉譯小工具,請接 widgetinstall 聽服務背景工作角色中的事件,並使用 widgets.updateByTag 函式更新小工具:

// Listen to the widgetinstall event.
self.addEventListener("widgetinstall", event => {
  // The widget just got installed, render it using renderWidget.
  // Pass the event.widget object to the function.
  event.waitUntil(renderWidget(event.widget));
});

async function renderWidget(widget) {
  // Get the template and data URLs from the widget definition.
  const templateUrl = widget.definition.msAcTemplate;
  const dataUrl = widget.definition.data;

  // Fetch the template text and data.
  const template = await (await fetch(templateUrl)).text();
  const data = await (await fetch(dataUrl)).text();

  // Render the widget with the template and data.
  await self.widgets.updateByTag(widget.definition.tag, {template, data});
}

更新服務背景工作角色更新的小工具

當 PWA 中的服務背景工作程式代碼變更時,瀏覽器會偵測到該變更、安裝新的服務背景工作角色,然後稍後啟動服務背景工作角色。

發生這種情況時,請務必更新可能已在執行中的任何小工具實例。 在發出服務背景 activate 工作角色事件之前,可能已安裝小工具。 若要避免顯示空的小工具,請在事件發生時更新您的小工具activate

// Update the widgets to their initial states
// when the service worker is activated.
self.addEventListener("activate", event => {
  event.waitUntil(updateWidgets());
});

async function updateWidgets() {
  // Get the widget that match the tag defined in the web app manifest.
  const widget = await self.widgets.getByTag("pwamp");
  if (!widget) {
    return;
  }

  // Using the widget definition, get the template and data.
  const template = await (await fetch(widget.definition.msAcTemplate)).text();
  const data = await (await fetch(widget.definition.data)).text();

  // Render the widget with the template and data.
  await self.widgets.updateByTag(widget.definition.tag, {template, data});
}

處理小工具動作

如果小工具範本包含動作,用戶可以按下轉譯小工具中的按鈕來執行這些動作。 如需如何在範本中定義動作的資訊,請參閱 定義小工具動作

當使用者執行小工具動作時, widgetclick 會在 PWA 服務背景工作角色中觸發事件。 若要處理使用者動作,請接聽 事件:

self.addEventListener('widgetclick', (event) => {
  switch (event.action) {
    case 'previous-song':
      // Application logic to play the previous song...
      break;
    case 'next-song':
      // Application logic to play the next song...
      break;
  }
});

為了簡潔起見,上述代碼段不會顯示實際的應用程式程序代碼。 previous-song收到 或 next-song 動作時,可能需要使用 Client.postMessage 將訊息傳送至應用程式,讓應用程式知道它應該開始播放上一首或下一首歌曲。

請注意, action 傳遞至上述事件接聽程式之物件的 widgetEvent 屬性符合小工具範本欄位中 action.verb 定義的字串。

如需事件的 widgetclick 詳細資訊,以及您可以從中存取哪些資訊,請參閱下面 的服務背景工作角色 API 參考

更新應用程式變更的小工具

在上一節中,您已瞭解如何在發生特定小工具事件、小工具動作和服務背景工作更新時更新小工具。 當應用程式中發生某事或推播通知發生時,或是定期更新小工具也很有用。

在本節中,您將瞭解如何使用定期背景同步 API 定期更新小工具。 如需定期背景同步 API 的詳細資訊,請參閱 使用定期背景同步 API 定期取得最新內容

在下列代碼段中,會使用事件接聽程式來回應應用程式小工具的各種生命週期事件。 偵測到小工具安裝時,會註冊定期同步處理,而偵測到移除小工具時,會取消註冊定期同步處理。

發生定期同步事件時,會使用 widgets.updateByTag 函式更新小工具實例。

self.addEventListener("widgetinstall", event => {
  event.waitUntil(onWidgetInstall(event.widget));
});

self.addEventListener("widgetuninstall", event => {
  event.waitUntil(onWidgetUninstall(event.widget));
});

async function onWidgetInstall(widget) {
  // Register a periodic sync, if this wasn't done already.
  // We use the same tag for the sync registration and the widget to
  // avoid registering several periodic syncs for the same widget.
  const tags = await self.registration.periodicSync.getTags();
  if (!tags.includes(widget.definition.tag)) {
    await self.registration.periodicSync.register(widget.definition.tag, {
      minInterval: widget.definition.update
    });
  }

  // And also update the instance.
  await updateWidget(widget);
}

async function onWidgetUninstall(widget) {
  // On uninstall, unregister the periodic sync.
  // If this was the last widget instance, then unregister the periodic sync.
  if (widget.instances.length === 1 && "update" in widget.definition) {
    await self.registration.periodicSync.unregister(widget.definition.tag);
  }
}

// Listen to periodicsync events to update all widget instances
// periodically.
self.addEventListener("periodicsync", async event => {
  const widget = await self.widgets.getByTag(event.tag);

  if (widget && "update" in widget.definition) {
    event.waitUntil(updateWidget(widget));
  }
});

async function updateWidget(widget) {
  // Get the template and data URLs from the widget definition.
  const templateUrl = widget.definition.msAcTemplate;
  const dataUrl = widget.definition.data;

  // Fetch the template text and data.
  const template = await (await fetch(templateUrl)).text();
  const data = await (await fetch(dataUrl)).text();

  // Render the widget with the template and data.
  await self.widgets.updateByTag(widget.definition.tag, {template, data});
}

示範應用程式

PWAmp 是音樂播放程式 PWA 示範應用程式,可定義小工具。 PWAmp 小工具可讓使用者將目前歌曲可視化,並播放上一首或下一首歌曲。

  1. 如果尚未完成,請安裝 WinAppSDK 1.2 ,並在 Windows 11 中啟用開發人員模式。

  2. 移至 PWAmp ,並在 Windows 11 上安裝應用程式。

  3. 按 Windows 標誌鍵 + W 開啟 Windows 11 小工具面板。

  4. 按兩下 [新增小工具 ] 以開啟 小工具設定 畫面,捲動至 PWAmp 迷你播放 機小工具並加以新增。

  5. 關閉 小工具設定 畫面。 PWAmp 迷你播放機現在會顯示在小工具面板中。

PWAmp 小工具會顯示目前要播放上一首或下一首歌曲的歌曲和按鈕。

PWAmp 示範應用程式旁的 Windows 小工具面板。小工具面板包含 PWAmp 迷你播放機小工具,其中顯示目前在 PWAmp 應用程式中播放的歌曲

服務背景工作角色 API 參考

服務背景工作角色全域物件 (或 ServiceWorkerGlobalScope) 包含公開 widgets 下列 Promise 型方法的屬性:

方法 描述 參數 傳回值
getByTag(tag) 依標記取得小工具。 小工具標籤 Promise,解析為符合標記 的小工具物件 ,或 undefined
getByInstanceId(id) 依實例標識碼取得小工具。 小工具實例標識碼 可解析為對應 小工具物件的承諾,或 undefined
getByHostId(id) 依主機標識碼取得小工具。 主機標識碼 在該主機中找到 的小工具對象 數位。
matchAll(options) 藉由比對選項取得小工具。 widgetOptions 物件 Promise,解析為符合準則 的小工具對象options 列。
updateByInstanceId(id, payload) 依實例標識碼更新小工具。 實例標識碼和 widgetPayload 物件 解析為 undefinedError的承諾。
updateByTag(tag, payload) 依標籤更新小工具。 小工具標籤和 widgetPayload 物件 解析為 undefinedError的承諾。

服務工作者全域物件也會定義下列事件:

  • widgetinstall:當小工具主機正在安裝小工具時引發。
  • widgetuninstall:當小工具主機卸載小工具時引發。
  • widgetresume:當小工具主機繼續轉譯已安裝的小工具時引發,這會在主機暫停轉譯小工具以保留資源之後發生。
  • widgetclick:當使用者執行其中一個小工具動作時引發。

如需這些事件所提供之對象的詳細資訊,請參閱下方 的 widgetEvent 物件widgetClickEvent 物件

Widget 物件

每個小工具都會以 widget 物件表示,其中包含下列屬性:

widgetOptions 物件

使用 matchAll(options) 取得多個小工具時, widgetOptions 必須要有 物件才能篩選要傳回哪些小工具。 物件 widgetOptions 包含下列屬性,所有屬性都是選擇性的:

  • installable:布爾值,指出傳回的小工具是否應可安裝。
  • installed:布爾值,指出傳回的小工具是否安裝在小工具主機中。
  • tag:字串,用來依標籤篩選傳回的小工具。
  • instanceId:字串,用來依實例標識符篩選傳回的小工具。
  • hostId:字串,用來依小工具主機標識元篩選傳回的小工具。

widgetPayload 物件

建立或更新小工具實例時,服務工作者必須傳送填入小工具所需的範本和數據。 範本和數據稱為 承載。 物件 widgetPayload 包含下列屬性:

  • template:作為字串的範本,用來呈現小工具。 這會是調適型卡片範本的字串化 JSON。
  • data:要與小工具範本搭配使用的資料做為字串。 此數據可以是字串化的 JSON 數據。

widgetInstance 物件

此物件代表小工具主機中小工具的指定實例,並包含下列屬性:

  • id:用來參考實例的內部 GUID 字串。
  • host:已安裝此實例之小工具主機的內部指標。
  • updated Date:物件,表示上次將數據傳送至 實例的時間。
  • payloadwidgetPayload 物件 ,表示傳送到這個實例的最後一個承載。

widgetDefinition 物件

這個物件代表小工具的原始定義,可在 PWA 指令清單檔案中找到。 這個物件的屬性符合上面定義 小工具中所列的屬性。

widgetEvent 物件

這個物件會當做自變數傳遞給類型 widgetinstall為、 widgetuninstallwidgetresume之服務背景工作角色小工具事件的接聽程式。

widgetinstall針對、 widgetuninstallwidgetresume 事件類型,widgetEvent物件具有下列屬性:

屬性 描述 類型
widget 觸發事件的小工具實例。 控件
instanceId 小工具實例標識碼。 String
hostId 小工具主機標識碼。 String

widgetClickEvent 物件

這個物件會當做自變數傳遞給 類型 widgetclick之服務背景工作小工具事件的接聽程式。 您可以使用 clients.openWindow()開啟應用程式的視窗以widgetclick回應事件。

物件 widgetClickEvent 具有下列屬性:

屬性 描述 類型
action 觸發事件的動作,如小工具範本欄位中 actions.verb 所定義。 請參閱 定義小工具動作 String
widget 觸發事件的小工具實例。 widgetInstance
hostId 小工具主機標識碼。 String
instanceId 小工具實例標識碼。 String