Indeksowanie stron offline za pomocą interfejsu Content Indexing API

Włączanie obsługiwanych przez usługę workerów, aby informowały przeglądarki, które strony działają offline

Czym jest interfejs Content Indexing API?

Korzystanie z progresywnej aplikacji internetowej oznacza dostęp do ważnych informacji – obrazów, filmów, artykułów i innych – niezależnie od aktualnego stanu połączenia z internetem. Technologie takie jak elementy usługi, interfejs Cache Storage APIIndexedDB stanowią elementy składowe umożliwiające przechowywanie i przekazywanie danych, gdy użytkownicy bezpośrednio wchodzą w interakcję z PWA. Jednak tworzenie wysokiej jakości PWA z możliwością korzystania offline to tylko część historii. Jeśli użytkownicy nie będą wiedzieć, że treści aplikacji internetowej są dostępne w trybie offline, nie wykorzystają w pełni pracy, jaką włożysz w wdrożenie tej funkcji.

To problem wykrywalności: jak Twoja PWA może poinformować użytkowników o dostępnych treściach offline, aby mogli je odkryć i zobaczyć? Rozwiązaniem tego problemu jest interfejs Content Indexing API. Część tego rozwiązania przeznaczona dla deweloperów to rozszerzenie dla usług działających w tle, które umożliwia deweloperom dodawanie adresów URL i metadanych stron obsługujących tryb offline do indeksu lokalnego zarządzanego przez przeglądarkę. Ta funkcja jest dostępna w Chrome w wersji 84 i nowszych.

Gdy indeks zostanie wypełniony treściami z Twojej aplikacji PWA oraz z innych zainstalowanych aplikacji PWA, przeglądarka wyświetli go w ten sposób:

Zrzut ekranu elementu menu Pobrane na nowej karcie w Chrome
Na stronie nowej karty w Chrome wybierz menu Pobrane.
Multimedia i artykuły dodane do indeksu.
Treści multimedialne i artykuły dodane do indeksu będą wyświetlane w sekcji Artykuły dla Ciebie.

Dodatkowo Chrome może aktywnie polecać treści, gdy wykryje, że użytkownik jest offline.

Interfejs Content Indexing API nie jest alternatywnym sposobem na buforowanie treści. Jest to sposób na udostępnianie metadanych stron, które są już zapisane w pamięci podręcznej przez usługę, aby przeglądarka mogła wyświetlić te strony, gdy użytkownicy prawdopodobnie będą chcieli je zobaczyć. Interfejs Content Indexing API pomaga w wykrywalności stron z pamięci podręcznej.

Zobacz, jak to działa

Najlepszym sposobem na zapoznanie się z interfejsem Content Indexing API jest wypróbowanie przykładowej aplikacji.

  1. Upewnij się, że używasz obsługiwanej przeglądarki i platformy. Obecnie ta funkcja jest ograniczona do Chrome 84 lub nowszej wersji na Androida. Otwórz about://version, aby sprawdzić, której wersji Chrome używasz.
  2. Otwórz stronę https://contentindex.dev.
  3. Kliknij przycisk + obok co najmniej 1 elementu na liście.
  4. (Opcjonalnie) Wyłącz połączenie z Wi-Fi i komórkową transmisję danych na urządzeniu lub włącz tryb samolotowy, aby symulować pracę przeglądarki w trybie offline.
  5. W menu Chrome wybierz Pobrania i otwórz kartę Artykuły dla Ciebie.
  6. Przeglądaj wcześniej zapisane treści.

Kod źródłowy przykładowej aplikacji znajdziesz na GitHubie.

Kolejna przykładowa aplikacja, scrapbook PWA, pokazuje wykorzystanie interfejsu Content Indexing API z interfejsem Web Share Target API. Kod pokazuje technikę, która umożliwia utrzymywanie synchronizacji interfejsu Content Indexing API z elementami przechowywanymi przez aplikację internetową za pomocą interfejsu Cache Storage API.

Korzystanie z interfejsu API

Aby korzystać z interfejsu API, aplikacja musi mieć usługę workera i adresy URL, które można przeglądać w trybie offline. Jeśli Twoja aplikacja internetowa nie ma obecnie serwisu workera, biblioteki Workbox mogą ułatwić jego utworzenie.

Jakie adresy URL mogą być indeksowane jako adresy umożliwiające działanie w trybie offline?

Interfejs API obsługuje indeksowanie adresów URL odpowiadających dokumentom HTML. Adres URL pliku multimedialnego w pamięci podręcznej nie może zostać zindeksowany bezpośrednio. Zamiast tego musisz podać URL strony, która wyświetla treści multimedialne i działa w trybie offline.

Zalecanym wzorcem jest utworzenie strony HTML „widok”, która może akceptować podstawowy adres URL multimediów jako parametr zapytania, a następnie wyświetlać zawartość pliku, prawdopodobnie z dodatkowymi elementami sterującymi lub treściami na stronie.

Aplikacje internetowe mogą dodawać do indeksu treści tylko adresy URL, które znajdują się w zakresie bieżącego pracownika obsługi. Innymi słowy, aplikacja internetowa nie może dodać do indeksu treści adresu URL należącego do zupełnie innej domeny.

Omówienie

Interfejs Content Indexing API obsługuje 3 operacje: dodawanie, wyświetlanie i usuwanie metadanych. Te metody są dostępne w ramach nowej właściwości index, która została dodana do interfejsu ServiceWorkerRegistration.

Pierwszym krokiem w indeksowaniu treści jest uzyskanie odwołania do bieżącego pliku ServiceWorkerRegistration. Najprostszym sposobem jest użycie navigator.serviceWorker.ready:

const registration = await navigator.serviceWorker.ready;

// Remember to feature-detect before using the API:
if ('index' in registration) {
  // Your Content Indexing API code goes here!
}

Jeśli wywołujesz interfejs Content Indexing API z serwisowego workera, a nie z poziomu strony internetowej, możesz bezpośrednio odwoływać się do ServiceWorkerRegistration za pomocą registration. Już jest zdefiniowany w ramach ServiceWorkerGlobalScope.

Dodawanie do indeksu

Użyj metody add(), aby zindeksować adresy URL i powiązane z nimi metadane. To Ty decydujesz, kiedy elementy mają być dodawane do indeksu. Możesz dodać do indeksu informacje uzyskane w odpowiedzi na dane wejściowe, np. po kliknięciu przycisku „Zapisz offline”. Możesz też dodawać elementy automatycznie za każdym razem, gdy dane w pamięci podręcznej zostaną zaktualizowane za pomocą mechanizmu takiego jak okresowa synchronizacja w tle.

await registration.index.add({
  // Required; set to something unique within your web app.
  id: 'article-123',

  // Required; url needs to be an offline-capable HTML page.
  url: '/articles/123',

  // Required; used in user-visible lists of content.
  title: 'Article title',

  // Required; used in user-visible lists of content.
  description: 'Amazing article about things!',

  // Required; used in user-visible lists of content.
  icons: [{
    src: '/img/article-123.png',
    sizes: '64x64',
    type: 'image/png',
  }],

  // Optional; valid categories are currently:
  // 'homepage', 'article', 'video', 'audio', or '' (default).
  category: 'article',
});

Dodanie wpisu wpływa tylko na indeks treści i nie dodaje niczego do pamięci podręcznej.

Wyjątek: wywołaj funkcję add() z kontekstu window, jeśli ikony korzystają z obsługi fetch.

Gdy wywołasz funkcję add(), Chrome wysyła żądanie dotyczące adresu URL każdej ikony, aby mieć kopię ikony do użycia podczas wyświetlania listy zindeksowanych treści.

  • Jeśli wywołasz add() z kontekstu window (czyli z Twojej strony internetowej), to żądanie spowoduje wywołanie zdarzenia fetch w Twoim serwisie.

  • Jeśli wywołasz funkcję add() w skrypcie service worker (np. w ramach innego przetwarzacza zdarzeń), żądanie nie spowoduje wywołania przetwarzacza fetch skryptu service worker. Ikony będą pobierane bezpośrednio, bez udziału skryptu. Pamiętaj o tym, jeśli ikony są zależne od modułu fetch, być może dlatego, że istnieją tylko w lokalnym pamięci podręcznej, a nie w sieci. Jeśli tak, zadzwoń do add() tylko z kontekstu window.

Wykaz zawartości indeksu

Metoda getAll() zwraca obietnicę dotyczącą przekształcalnej listy zindeksowanych wpisów i ich metadanych. Zwrócone wpisy będą zawierać wszystkie dane zapisane za pomocą funkcji add().

const entries = await registration.index.getAll();
for (const entry of entries) {
  // entry.id, entry.launchUrl, etc. are all exposed.
}

Usuwanie elementów z indeksu

Aby usunąć element z indeksu, wywołaj funkcję delete(), podając id elementu, który ma zostać usunięty:

await registration.index.delete('article-123');

Wywołanie funkcji delete() ma wpływ tylko na indeks. Nie usuwa niczego z pamięci podręcznej.

Obsługa zdarzenia usunięcia użytkownika

Gdy przeglądarka wyświetla zindeksowane treści, może zawierać własny interfejs z opcją Usuń, która umożliwia użytkownikom wskazanie, że skończyli przeglądanie wcześniej zindeksowanych treści. Tak wygląda interfejs usuwania w Chrome 80:

Pozycja menu Usuń.

Gdy ktoś wybierze ten element menu, worker usługi Twojej aplikacji internetowej otrzyma zdarzenie contentdelete. Obsługa tego zdarzenia jest opcjonalna, ale daje możliwość „posprzątania” treści, takich jak pliki multimedialne w pamięci podręcznej, z których użytkownik nie korzysta już.

Nie musisz wywoływać funkcji registration.index.delete() w obiekcie contentdelete. Jeśli zdarzenie zostało wywołane, przeglądarka już wykonała usunięcie odpowiedniego indeksu.

self.addEventListener('contentdelete', (event) => {
  // event.id will correspond to the id value used
  // when the indexed content was added.
  // Use that value to determine what content, if any,
  // to delete from wherever your app stores it—usually
  // the Cache Storage API or perhaps IndexedDB.
});

Opinie na temat projektu interfejsu API

Czy interfejs API jest niewygodny lub nie działa zgodnie z oczekiwaniami? A może brakuje Ci elementów, których potrzebujesz do wdrożenia swojego pomysłu?

Zgłoś problem w repozytorium GitHub tłumaczenia interfejsu Content Indexing API lub dodaj swoje uwagi do istniejącego problemu.

Problem z implementacją?

Czy znalazłeś/znalazłaś błąd w implementacji Chrome?

Zgłoś błąd na stronie https://new.crbug.com. Podaj jak najwięcej szczegółów, proste instrukcje odtwarzania błędu i ustaw wartość Components na Blink>ContentIndexing.

Planujesz korzystać z interfejsu API?

Planujesz użyć interfejsu Content Indexing API w aplikacji internetowej? Twoje publiczne wsparcie pomaga Chrome ustalać priorytety funkcji i pokazuje innym dostawcom przeglądarek, jak ważne jest ich wsparcie.

Jakie są konsekwencje indeksowania treści dla bezpieczeństwa i prywatności?

Zapoznaj się z odpowiedziami na ankikietę dotyczącą bezpieczeństwa i prywatności W3C. Jeśli masz więcej pytań, rozpocznij dyskusję w repozytorium GitHub projektu.

Baner powitalny autorstwa Maksym Kaharlytskyi z Unsplash.