Content Index API

实验性: 这是一项实验性技术
在生产中使用此技术之前,请仔细检查浏览器兼容性表格

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

Content Index API 允许开发者向浏览器注册其支持离线使用的内容。

概念与用法

目前,用户难以发现离线 Web 内容。内容索引允许开发者告知浏览器其特定的离线内容。这使得用户能够发现和查看可用内容,同时让开发者能够添加和管理这些内容。例如,新闻网站可以在后台预加载最新文章,或者内容流应用可以注册已下载的内容。

Content Index API 是 Service Worker 的一个扩展,它允许开发者在当前 Service Worker 的作用域内添加已缓存页面的 URL 和元数据。浏览器随后可以使用这些条目向用户显示离线阅读内容。作为开发者,你也可以在你的应用程序中显示这些条目。

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

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

接口

ContentIndex 实验性

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

ContentIndexEvent 实验性

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

其他接口的扩展

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

ServiceWorkerRegistration.index 只读 实验性

返回一个指向 ContentIndex 接口的引用,用于索引已缓存的页面。

contentdelete 事件 实验性

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

示例

以下所有示例都假定已注册 Service Worker。有关更多信息,请参阅 Service Worker 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);
}

以上所有方法都可以在 Service Worker 的作用域内访问。它们可以通过 `WorkerGlobalScope.self` 属性访问。

js
// service worker script

self.registration.index.add(item);

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

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

contentdelete 事件

当用户代理界面中的某个条目被移除时,Service Worker 会收到一个 `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() 方法时,不会触发此事件。

规范

规范
Content Index

浏览器兼容性

api.ContentIndex

api.ServiceWorkerRegistration.index

另见