内容索引 API

实验性: 这是一个 实验性技术
在生产环境中使用此功能之前,请仔细查看 浏览器兼容性表

注意: 此功能在 Web Workers 中可用。

内容索引 API 允许开发者将他们支持离线的网页内容注册到浏览器。

概念和用法

就目前而言,离线网页内容对用户来说并不容易发现。内容索引允许开发者告诉浏览器他们特定的离线内容。这允许用户发现和查看可用的内容,同时让开发者能够添加和管理这些内容。例如,新闻网站可以在后台预取最新的文章,或者内容流应用程序可以注册已下载的内容。

内容索引 API 是对 服务工作者 的扩展,它允许开发者在当前服务工作者的范围内添加已缓存页面的 URL 和元数据。然后,浏览器可以使用这些条目向用户显示离线阅读内容。作为开发者,你也可以在你的应用程序中显示这些条目。

已索引的条目不会自动过期。建议提供一个清除条目的界面,或者定期删除旧条目。

注意: 该 API 支持索引与 HTML 文档对应的 URL。例如,缓存媒体文件的 URL 无法直接索引。相反,你需要提供一个显示媒体的页面 URL,并且该页面能够离线工作。

接口

ContentIndex 实验性

提供注册离线可用内容的功能。

ContentIndexEvent 实验性

定义用于表示 contentdelete 事件的对象。

对其他接口的扩展

内容索引 API 规范中指定了以下对 ServiceWorker 的补充,以提供使用内容索引的入口点。

ServiceWorkerRegistration.index 只读 实验性

返回对用于索引缓存页面的 ContentIndex 接口的引用。

contentdelete 事件 实验性

当内容被用户代理移除时触发。

示例

以下所有示例都假定已注册服务工作者。有关更多信息,请参阅 服务工作者 API

功能检测和接口访问

这里我们获取对 ServiceWorkerRegistration 的引用,然后检查 index 属性,该属性使我们可以访问内容索引接口。

js
// reference registration
const registration = await navigator.serviceWorker.ready;

// feature detection
if ("index" in registration) {
  // Content Index API functionality
  const contentIndex = registration.index;
}

添加到内容索引

这里我们以正确的格式声明一个项目,并创建一个异步函数,该函数使用 add() 方法将其注册到内容索引。

js
// our content
const item = {
  id: "post-1",
  url: "/posts/amet.html",
  title: "Amet consectetur adipisicing",
  description:
    "Repellat et quia iste possimus ducimus aliquid a aut eaque nostrum.",
  icons: [
    {
      src: "/media/dark.png",
      sizes: "128x128",
      type: "image/png",
    },
  ],
  category: "article",
};

// our asynchronous function to add indexed content
async function registerContent(data) {
  const registration = await navigator.serviceWorker.ready;

  // feature detect Content Index
  if (!registration.index) {
    return;
  }

  // register content
  try {
    await registration.index.add(data);
  } catch (e) {
    console.log("Failed to register content: ", e.message);
  }
}

检索当前索引中的项目

下面的示例显示了一个异步函数,该函数检索内容索引中的项目,并迭代每个条目,为接口构建一个列表。

js
async function createReadingList() {
  // access our service worker registration
  const registration = await navigator.serviceWorker.ready;

  // get our index entries
  const entries = await registration.index.getAll();

  // create a containing element
  const readingListElem = document.createElement("div");

  // test for entries
  if (entries.length === 0) {
    // if there are no entries, display a message
    const message = document.createElement("p");
    message.innerText =
      "You currently have no articles saved for offline reading.";

    readingListElem.append(message);
  } else {
    // if entries are present, display in a list of links to the content
    const listElem = document.createElement("ul");

    for (const entry of entries) {
      const listItem = document.createElement("li");

      const anchorElem = document.createElement("a");
      anchorElem.innerText = entry.title;
      anchorElem.setAttribute("href", entry.url);

      listElem.append(listItem);
    }

    readingListElem.append(listElem);
  }
}

取消注册已索引的内容

下面是一个异步函数,它从内容索引中移除一个项目。

js
async function unregisterContent(article) {
  // reference registration
  const registration = await navigator.serviceWorker.ready;

  // feature detect Content Index
  if (!registration.index) return;

  // unregister content from index
  await registration.index.delete(article.id);
}

以上所有方法都在 服务工作者 的范围内可用。它们可以通过 WorkerGlobalScope.self 属性访问。

js
// service worker script

self.registration.index.add(item);

self.registration.index.delete(item.id);

const contentIndexItems = self.registration.index.getAll();

contentdelete 事件

当项目从用户代理界面中移除时,服务工作者会收到一个 contentdelete 事件。

js
self.addEventListener("contentdelete", (event) => {
  console.log(event.id);

  // logs content index id, which can then be used to determine what content to delete from your cache
});

contentdelete 事件仅在删除是由于与浏览器的内置用户界面交互而发生时才会触发。当调用 ContentIndex.delete() 方法时,它不会触发。

规范

规范
内容索引

浏览器兼容性

api.ContentIndex

BCD 表格仅在浏览器中加载

api.ServiceWorkerRegistration.index

BCD 表格仅在浏览器中加载

另请参阅